what's the point of workers?

Hi, I'm new to cloudflare workers. Trying to figure out what even is the point if you can't seemingly import your libraries?? Like I'm trying to add a custom watermark to my image (cuz cloudflares apo didn't work for some reason) using canvas/jimp, and I can't even do that? I think it's a skill issue but then how do I import node libraries?
60 Replies
Chaika
Chaika2w ago
Workers aren't node, they're v8 (chrome's js engine) with a web-like environment. There's some node compat: https://developers.cloudflare.com/workers/runtime-apis/nodejs/ but a lot of stuff isn't going to be supported no matter what, like file system or raw network access
Cloudflare Docs
Node.js compatibility · Cloudflare Workers docs
Implemented Node.js runtime APIs and enablement instructions for your Worker project.
Chaika
Chaika2w ago
You can import libraries which are built for the web/don't depend on node stuff, or ones that only depend on stuff which is supported like buffer
Murzin
Murzin2w ago
ok starting to get it. How can I do that? For example, import jimp
Chaika
Chaika2w ago
In a larger sense, Workers run on the same machine as your request hits, in all ~330 or however many CF Locations, so they need to be lean (even Paid is restricted at 10 mb), super fast to startup, and fast: https://developers.cloudflare.com/workers/reference/how-workers-works/
Cloudflare Docs
How Workers works · Cloudflare Workers docs
The difference between the Workers runtime versus traditional browsers and Node.js.
Murzin
Murzin2w ago
gotcha. I just need to add watermark to my image. In my nuzt3 serverit takes about 200ms in server-side with jimp
Chaika
Chaika2w ago
You can google and see if anyone got it working with Workers, or try to see what people are using, as jimp says though "written for node" and looks like its options are file system (doesn't exist) or http depending on a node network lib which isn't going to work either
Murzin
Murzin2w ago
aha, got it what about cloudflares own API for adding watermarks? I tried it yesterdat, and for some reason it literally just returned the image, with no added watermark. I'd provide code, but can't at the moment sadly
Chaika
Chaika2w ago
(may worth mentioning that's going to be way too long for free, would need Workers Paid anyway, free only gets 10ms of CPU Time)
Murzin
Murzin2w ago
yeah, I'm on paid version appreciate the mention
Chaika
Chaika2w ago
You mean Image Transformations? It'll only work on a route/custom domain, and then make sure you have it enabled for that website/zone (under Images -> Transformations) if you don't have it enabled, it'll just return it untransformed
Murzin
Murzin2w ago
Okay. The other thing I worry about is how's that gonna work for my case. I need to transform the image user uploaded BEFORE uploading it to the R2 I'm using. Can I somehow load an image using base64? Or do I have to upload it to the server first, and then have the worker fetch it? Cuz I'm using nuxthub with cloudflare r2 integration, and my media is settled up in a specifics domain media.jart.lol/"imagelink", which is cache configured and anything. So I'd like to keep the same domain media.jsrt.lol
Chaika
Chaika2w ago
I don't believe there's any way around uploading it first, you could try though via a data uri fwiw's image transformation's billing is built around not doing that. It costs you the same to transform one unique image/settings once in a month as it does a million times
Murzin
Murzin2w ago
Meaning that I can't just fetch the new link workers will output, I need to send workers local image user uploaded, then receive the image, and upload it to r2 So, you mean I should upload it first, then have the workers upload transformed version, and use the transformed images link? And to delete the first uploaded non-transformed image? Cuz my use case is getting images from the user and uploading them. It's not static images or anything. Huge image input per month. Maybe like 500-1000 images And all images are gonna be unique
Chaika
Chaika2w ago
yea, upload to r2 -> fetch transformed -> put transformed into r2, sometimes you want to keep the original anyway
Murzin
Murzin2w ago
Do you think it's viable as an infrastructure? Uploading 2x amount the images?
Chaika
Chaika2w ago
keeping the original, or what exactly? images are usually pretty small. It really depends on what you're doing. I can understand why for a free project you'd want to delete the originals, for one people are paying for, I've kept the original and then transformed version(s)
Murzin
Murzin2w ago
Got you. Really appreciate it, it helps a lot! Will try tackling my way through it
Chaika
Chaika2w ago
sure, some of its just paranoria too "what if a user uploaded a copy of an important picture, deleted it from their end, and the one in a billion chance happened and the image library/api returned junk on trying to transform it, so we just lost it" I've never had/heard of CF's Transformation return junk with no error/a useless image, but just saying
Murzin
Murzin2w ago
Haha, okay Oh And one more question if we're talking about cloudflares transformations Ideally, I'd want to use nuxtimage to serve different sized images to people on mobiles and desktops Does it also make copy of images on cloudflsre when I transform them like that?
Chaika
Chaika2w ago
If you're using CF's integration, you mean? https://image.nuxt.com/providers/cloudflare
Nuxt Image
Cloudflare - Nuxt Image Providers
Nuxt Image has first class integration with Cloudflare.
Murzin
Murzin2w ago
Yes
Chaika
Chaika2w ago
no, it's just temp in cache based on the settings you input
Murzin
Murzin2w ago
Niceee
Chaika
Chaika2w ago
and if you're on the latest images plan, you're only billed once for a unique transformation per month, regardless of cache https://developers.cloudflare.com/images/pricing/#images-transformed
Murzin
Murzin2w ago
That's really convenient Got you And can you advice me what baseURl stands for? In nuxtImg
Chaika
Chaika2w ago
I have never used that component before but it looks like it's just the root your website will live on, ex: if you deploy your project on mycoolproject.mydomain.com, it'd be https://mycoolproject.mydomain.com, so that it can use https://mycoolproject.mydomain.com/cdn-cgi/image/ for image transformations
Murzin
Murzin2w ago
Got you! I just noticed the pricing tags for transformations - goddamn. Will think about it, but prob gonna be tought as I have like 1000 images/user each month. On a free plan of my product that sucks Appreciate it once again. I also wanted to ask about how can I deploy my custom backend alongside my deployed cloudflare pages website. Can I ask you about it, or should I ask somewhere else? I wanna deploy python, maybe rust. Or even a custom JavaScript without limitations of workers
Chaika
Chaika2w ago
just as a normal origin hosted on a vps somewhere/some other infra? Just a proxied record will do, and if you need SSL CF has Origin Certificates under SSL/TLS -> Origin Server which last for 15 years and are trusted by CF
Murzin
Murzin2w ago
If origin hosted means on the same domain with 0 ping then yes (sorry for my lack of knowledge) So will the ping be 0, and will count as local if I deploy it with origin certificate?
Chaika
Chaika2w ago
Oh, when you say want to deploy, you were asking for providers/options? CF has nothing but Workers for deploying code, no container or vps offerings You'd need to find a different provider, either more managed like fly.io/container level, or a vps provider, and throw rust/python on there. CF Workers has some support for Python (But no packages) and Rust (but limited, all the other workers limits still apply)
Murzin
Murzin2w ago
I can deploy it on something like Railway (which is similar to fly.io), but will I be able to get the ping to 0 between my cloudflare pages deployed website, and this deployed backend? If I use the same domain
Chaika
Chaika2w ago
0 ping is impossible, even you were running it on a server physically next to you, both connected to the same LAN, there would still be some latency If your Pages app was calling your railway app/backend from a function/worker, there's going to be some latency to get to Railway yea If your client calls the backend/you are using client-side js to do fetches to your backend, then you have User -> ISP -> Railway (which is just GCP iirc) User -> ISP -> CF
Murzin
Murzin2w ago
yeah and the main problem would be that while cloudflsre has a great cdn, so the ping for users will be minimal, but Railway only has one server. So for Europeans it's gonna be so slow
Chaika
Chaika2w ago
they don't have more then one still? rip I mean that's the issue every app faces though. You have to give up something, or optimize for things
Murzin
Murzin2w ago
Think they do, but with highly payed plans. I'm using the cheapest for $5 Got you It's my first app where I really gotta think about infrastructure, so thanks a lot for that! I was thinking about adding watermark on client side Which is insanely easy and takes like 80ms
Chaika
Chaika2w ago
Even if you had the backend in tons of locations, your database layer would then either have to be eventually consistent, or sharding data, or all going back to one location/slow
Murzin
Murzin2w ago
But if user uploads 100 images, the time piles up, and PC explodes You're right
Chaika
Chaika2w ago
if it's client-side then you just queue and do it one at a time, slowly
Murzin
Murzin2w ago
Oooh wait Youre right In this case async parallelism would be worse So I gotta cap it at like 50 images per thread and wait for them to continue
Chaika
Chaika2w ago
you just have to decide if it's something they'd do so regularly that them waiting <a while> for them to all be transformed is enough that you'd want to offload it (ex: use a queue on your end and process them) server-side, or slowly do them client-side
Murzin
Murzin2w ago
Or somehow make a buffer with max 50 concurrent watermartk processing
Chaika
Chaika2w ago
In Javascript (at least, web-side) you only have a single thread lol
Murzin
Murzin2w ago
Then how does it run in parallelism?
Chaika
Chaika2w ago
the magical event loop
Chaika
Chaika2w ago
MDN Web Docs
The event loop - JavaScript | MDN
JavaScript has a runtime model based on an event loop, which is responsible for executing the code, collecting and processing events, and executing queued sub-tasks. This model is quite different from models in other languages like C and Java.
Chaika
Chaika2w ago
GeeksforGeeks
What is an event loop in JavaScript ? - GeeksforGeeks
A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.
From An unknown user
From An unknown user
From An unknown user
From An unknown user
Chaika
Chaika2w ago
Important thing: async != multi-threaded, two completely different things
Murzin
Murzin2w ago
Got you And if you use gpt in web? GPU*
Chaika
Chaika2w ago
like webgpu and such? The entire idea of a gpu is that you have something that you can send commands to, to do operations more efficiently. I have not worked with gpus on the web before, but I can say the sending side would still be sync/javascript, and the gpu would probably do multi-threading/its own work on its own time to handle commands, which shouldn't matter to you. The actual page loading/drawing /renderer is a whole different complex topic which depends on the specific browser, mostly not your concern when you use JS though There are ways to have background threads in js, using web workers, but my understanding is they're cumbersome to use and only fit some applications. May be worth looking into though
Murzin
Murzin2w ago
Got you. I will still think about it, but myaim options are: Server side, which takes 500ms in total per image Or client side with canvas with about 80ms, but obviously it can be too much for the client. Will prob try to make maximum concurrency buffer with 50 or smth. So it's gonna be 4 seconds per 50 images which is still not ideal, but worth looking into Thank you so much. I only recently got into webdev (7months or so), and only thanks to people like you I can learn so much faster!
Chaika
Chaika2w ago
Canvas can be cpu or gpu accelerated, depends on os/browser/etc, it just handles it all for you. You're still stuck waiting for each action to complete though
Murzin
Murzin2w ago
Can I ask you what would you do were you in my situation? If you needed to add watermark to EVERY image user uploads and do it fast for 1000 images? And if $0.5 per 1000 images was expensive for you?
Chaika
Chaika2w ago
Can I ask you what would you do were you in my situation? If you needed to add watermark to EVERY image user uploads and do it fast for 1000 images?
Does it have to be fast? What do you mean by fast?
And if $0.5 per 1000 images was expensive for you?
Depends on the product. To something people pay licenses for, $0.50 per 1k images is pretty cheap. For a free product/freenium product, could be expensive
Murzin
Murzin2w ago
Fast like if user uploads 1 image, adding watermark should be added in 200ms max. And, scaling up, if user is trying to upload 1000 images, ideally it would take about a 90 seconds. I've got a freemium model, and gotta minimize the costs as much as possivle
Chaika
Chaika2w ago
I mean like I said above it really comes down to what matters for you and your product. Are these paying customers, and people you want to have a good experience even when they upload 1,000 images? Then you could process them server-side in a queue. Are these free customers/low budget/you don't care if it takes 9 years to process 1,000 images on their old intel 2 core? then sounds like you'd want to just do it cilent-side
Murzin
Murzin2w ago
lol Every customer is precious to me, but I get what you mean
Chaika
Chaika2w ago
yes they're all the equal amount of precious which still isn't enough to justify the amount of dev work and compute for doing it server-side for free lol, is how I'd view it
Murzin
Murzin2w ago
Then just gotta make sure the operations, while may be slow, but are still smooth with no lags or crashes Cuz oh my, when my friend uploaded 2000 images, it wasn't looking too hot for his pc Times for one function were like 40s cuz they all have been fighting among themselves for the computing power of his PC lol It's like when I have one lane turn and 50 cars tryna fit in Gonna limit that to 10 at a time, and tell other 10 to chill
Tilon
Tilon2w ago
Also if you wanna do it client side, you could put that operation into a webworker which a) does not block the main UI while creating the watermarks and b) you can utilize several CPU cores. https://web.dev/articles/offscreen-canvas
web.dev
OffscreenCanvas—speed up your canvas operations with a web worker  ...
This document explains how you can use the OffscreenCanvas API to achieve performance improvements when rendering graphics in your web app.
Murzin
Murzin2w ago
really appreciate it, will check it out I made it work on the client side in about 30-40ms for now, not bad