The process of spawning and deploying a serverless Cloudflare worker is as simple as:
bit fork nitsan770.cloudflare-workers/counter
"nitsan770.cloudflare-workers/counter": {},
counter.app-root.ts
file with your logic.Congrats on your new Cloudflare worker component that deploys itself whenever you release a new version with Bit. ๐
My role as a frontend developer often requires me to use backend services. Very rarely, I could find an API that fit my requirements in the backend. Most of the time, that API does not exist or requires a major refactor to meet my needs.
This is one of the main reasons I decided to develop my projects in the JAMstack approach. JAMstack (stands for JavaScript, API, and Markup) is an architecture pattern that decouples the frontend from the backend and relays on using micro-services (or serverless functions) as its backend. Both the frontend and microservices are hosted on CDNs, very close to the end user. The result is super fast web pages that are easy to maintain and are very reliable.
Cloudflare workers do just that. They enable serverless functions to run as close to the end user as possible. The serverless code itself is 'cached' on the network, and it runs when the right type of request is received.
Throughout this guide, I will show you how you can use Cloudflare Workers along with Bit to create your own serverless components which will serve as a backend for your web pages.
The serverless workers you create with Bit can be very easily maintained since each worker is versioned, built, and deployed separately. Bit lets you document the services you build so that anyone wanting to interact with the workers' API (or fork them to reuse and extend them) will have a pleasant experience. As a result, it is easier to reuse and share the component with other developers.
Let's begin the service!
Cloudflare worker components are used by Bit for a wide range of purposes. This tutorial will show you how to create a simple reusable counter worker component. At Bit, we use similar components to perform tasks such as tracking the popularity of labels in the blog in order to display the most relevant content. Bit allows us to spawn new workers very easily and quickly, reuse them, upgrade them, and modify them. Here's a sneak peek of the component you will be creating (have a look at the code tab):
You will need to have Bit installedlocally, a bit.cloud account, a Cloudflare accountand know how to open a remote scopeto follow along with us. Almighty Gosh, that's a long list ๐ Let's get started!
First, we need to set up our workspace. Open the designated folder and run:
Ensure that your workspace.json file has the default scope set to your remote scope. For example, here are the adjustments I made to my workspace:
- "defaultScope": "my-scope"
+ "defaultScope": "nitsan770.cloudflare-workers"
Now it's time to create your first Cloudflare worker component! I'm really excited for you. ๐ค
To keep things simple, we're going to fork an existing component I made for this tutorial. It's going to be your own after you fork it so feel free to make and changes you want. In your Workspace folder, run:
Now add this line at the top level of your workspace.json
file:
"nitsan770.cloudflare-workers/counter": {},
Make sure your replace
nitsan770
with your username andcloudflare-workers
with the name of your scope.
After running bit install && bit compile
, Bit will be able to identify your as of app type:
bit app list
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโ
โ id โ name โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโค
โ nitsan770.cloudflare-workers/counter โ counter โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโ
We are all set to go ๐ Let's start writing some code!
After you've forked the worker component in your workspace, let's examine its source code.
The counter.app-root.ts
file represents the entry point for your worker. This is the file that will be executed when the worker is called.
It contains two handler functions:
handleOptions
: This function is invoked when the worker is passed an options object.handleRequest
: This function is invoked when the worker is called with a request object.We will be covering the handleRequest
function in this guide, but feel free to check out the handleOptions
function as well.
Here is how the handleRequest
function works, let's take a look at it:
async function handleRequest(request: any) {
let response: any;
if (request.method === "OPTIONS") {
response = handleOptions(request);
} else {
const { pathname } = new URL(request.url);
const currentCount = await COUNTER.get("count");
if (pathname.endsWith("/increment")) {
const newCount = currentCount ? +currentCount + 1 : 1;
await COUNTER.put("count", newCount);
} else if (pathname.endsWith("/decrement")) {
const newCount = currentCount ? +currentCount - 1 : -1;
await COUNTER.put("count", newCount);
}
const updatedCount = await COUNTER.get("count");
response = new Response(JSON.stringify({ count: updatedCount }));
response.headers.set("Access-Control-Allow-Origin", "*");
response.headers.set(
"Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS"
);
}
return response;
}
What do we have here?
By extracting the pathname
from the request.url
property, we can access the path of the request.
Next, we check if the path ends in /increment
or /decrement
.
If it does, we increment or decrement the counter, respectively.
Finally, we return the response to the client with the updated count.
Maybe you are wondering where that COUNTER variable comes from? Although we don't define it anywhere, we use it in the handleRequest
function to update (put
) and retrieve (get
) the counter value.
Well, this is a nice feature of Cloudflare Workers called Workers KV
.
Workers KV is a global, low-latency key-value store. The data is stored in a small number of centralized data centers, and then cached in Cloudflare's data centers after being accessed. Since KV delivers extremely high read volumes with low latency, you can build highly dynamic APIs and websites that respond as quickly as a cached file.
To make the KV storage accessible to your worker, you will need to bind the Worker to the KV storage.
Finally, the 'addEventListener' function receives the 'handleRequest' function:
addEventListener("fetch", (event: any) => {
event.respondWith(
handleRequest(event.request).catch(
(err) =>
new Response(err.stack, {
status: 500,
})
)
);
});
There we have a working worker. ๐ As we move forward with deploying our worker to the rest of the world, let's take a minute to document it so that anyone who wants to use it will understand what it does.
I promise you, it will be a lot of fun!
The documentation for Bit components is written in MDX (https://mdxjs.com/). Put anything you want into your component to make it more visually pleasing, no more boring sentences. Even service workers can be visualized!
Since this blog post is also written in MDX, I can simply display the component documentation here:
description: A Cloudflare worker that increments or decrements a counter.
Cloudflare Workers are serverless applications most often used to intercept and modify network requests (much like Service Workers in the browser).
This CF Worker sets a function to be triggered on a 'get' event that triggers an increment or decrement to the counters count.
The function returns a Response, containing the current count.
bit fork nitsan770.cloudflare-workers/counter
"nitsan770.cloudflare-workers/counter": {},
Edit counter.cf-worker.ts
file with your credentials.
Edit the counter.app-root.ts
file to add your logic.
Edit the environment variables in your worker settings.
Tag the component. Don't forget to add your cloudflare token as an env variable.
Documenting components with Bit has the advantage of being part of the component itself. The documentation is available every time someone visits your component, whether it's to install it or to import and extend it.
The documentation of backend services can also show a real example of how its API is used, as we did with the counter
component.
This allows the consumer to see how the API works and if it is working properly.
The last part of the guide explains how to deploy the worker to Cloudflare servers. This is actually the easiest part of the guide since the cloudflare-worker component(aspect) takes care of everything for you.
Just replace the credentials in the cloudflare-worker
aspect with your own:
deployOptions: {
// the auth token for cloudflare (https://developers.cloudflare.com/api/tokens/create)
auth: { token: process.env.CLOUDFLARE_TOKEN },
// your cloudflare account id
accountId: '37ec40bec82f25b95678f21f01ca64a0',
// the cloudflare hosting zone id
zoneId: 'ec8d03e740264543065fad46cb2c528f',
// the url for the deployed worker
routes: ['api.bit.cloud/blog-examples/counter/*'],
}
When we tag a cloudflare worker, Bit will also deploy your worker. You can always be sure the worker is up to date that way.
In the tagging process, your application (the worker) is also deployed:
โ env "teambit.apps/envs/cf-worker@0.0.5", task "teambit.harmony/application:deploy_application" has completed successfully in 3s
โ executing post-build for all tasks
โ teambit.pipelines/builder, running tag pipe for 1 environments, total 3 tasks (completed in 5s)
1 component(s) tagged
(use "bit export [collection]" to push these components to a remote")
(use "bit untag" to unstage versions)
changed components
(components that got a version bump)
> counter@0.0.4
We've covered the basics of building a cloudflare worker with Bit in this guide. In addition, we covered how to document the worker and deploy it to Cloudflare.
While it is easy to deploy the worker with Bit, the main benefit is that you always have a single source of data for your worker that is truly decoupled from the rest of your app.
If you have any questions, feel free to reach out on our Slack channel.
Thank you for reading this guide. I hope you enjoyed it. You can count on the Cloudflare worker we've built (OK, that's a good dad joke! ๐)