Build blazing fast serverless apps using Cloudflare 🏃
Tags: javascript, programming, aws, serverless
Published: 2023-10-05 14:31:38

## TL;DR

⚡Build a blazing fast Cloudflare worker that stores, and return random quotes.

## Intro

Do you like speed? 🏃 Do you like simplicity?Then, Cloudflare Workers might be the solution for your next application.

[Cloudflare](https://www.cloudflare.com/) is a cloud-provider, most-known for their CDN, offering several services to build cloud applications. Among them, **Cloudflare Workers is a serverless service that allows you to run serverless functions at edge** (like Lambda@Edge if you are an AWS user). This means that your code runs closer to end-users, resulting in **blazing fast response times**.


![Fast GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0lpvl5jj41y7low03g7j.gif)

**Disclaimer:** In my opinion Cloudflare Workers are best suited to small projets. I haven't found satisfying tools to deploy and manage several Cloudflare Workers on big projects. In that situation, a service like AWS Lambda is probably more suited.

That being said, Cloudflare Workers are super easy to setup and offer a great DevX if you want to deploy simple applications.

To show you that, we are going to build a simple worker, that allows you to save quotes in a key-value store, and return random quotes among the ones you saved.

## Creating your first worker 🥇

### Prerequisites

- [A Cloudflare account](https://dash.cloudflare.com/sign-up) (it is super easy to setup)

First create a new folder where your projet will reside. Inside this folder, you can add a `package.json` file:

```json
{
  "name": "awesome-quotes-service",
  "devDependencies": {
    "@cloudflare/workers-types": "^4.20230801.0",
    "typescript": "^5.1.6",
    "wrangler": "^3.3.0"
  }
}
```

We will be using Typescript, so you can also add a `tsconfig.json` file with your TS configuration:

```json
{
    "compilerOptions": {
      "target": "esnext",
      "module": "esnext",
      "lib": ["esnext"],
      "preserveSymlinks": true,
      "types": ["@cloudflare/workers-types"]
    }
  }
```

Then you can create an `index.ts` file that will contain the code of our function:

```jsx
export default {
  async fetch(
    request: Request,
    env: Env,
): Promise<Response> {

    return new Response(
      JSON.stringify('Hello from my first Cloudflare Worker'),
      {
        // Headers configuration of API response
        headers: {
          'content-type': 'application/json',
          'Access-Control-Allow-Headers': '*',
          'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
          'Access-Control-Allow-Origin': '*',
        },
      }
    );
  },
};
```

In this file, we are creating a `fetch` function that contains our Cloudflare Worker code. It takes as an input:

- A `request` variable containing your request data (eg. body, url, method etc…),
- An `env` variable, that contains the binding associated to your worker (more of that later…)

Inside it, we return a `Response` object that contains two parameters:

- The body of your response,
- Some response configuration, here our response headers

Finally, you can create a `wrangler.toml` file. **Wrangler is a command-line tool developed by Cloudflare that is used for building, deploying, and managing Cloudflare Workers.** We are going to use it here to configure our worker, and deploy it using the CLI.

```toml
// Name of your Cloudflare Worker
name = "quotes"
// A date which will be used to determine which version of the Workers runtime is used.
compatibility_date = "2023-07-21"
```

After installing your project dependencies using your favorite package manager, you can run `npx wrangler deploy ./index.ts` to tell Wrangler to deploy your worker to Cloudflare.

**Congratulations** 🎉, you just deployed your first worker 💪 ! The url where it is available should be displayed in your terminal. You should see our 'Hello from my first Cloudflare Worker' if you call this url.

## Going further

Now that we have a working worker 😲 we are going to take things one step further and add some storage to build our quotes service. For that we are going to use KV. **KV is a distributed and highly scalable key-value data store offered by Cloudflare.**

We’ll first need to set it up inside Cloudflare’s dashboard before using it in our worker. For that you can go to the `KV` tab once connected to your Cloudflare account, and select `Create a namespace` that you will call `quotes`.


![The KV Tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/thxa230k9vifjhwm1geh.png)

Now that we have a KV store we will be able to store, and retrieve random quotes in it. Let’s start by updating our worker to store quotes. We are going to add a `/create` HTTP route, that you can call with a quote to save it in KV.

We first need to update our `wrangler.toml` to define a binding with the `quotes` KV store to be able to refer it inside our code. You will need the id of your `quotes` KV store that you can find on the Cloudflare dashboard.

```toml
name = "quotes"
compatibility_date = "2023-07-21"
kv_namespaces = [
    { binding = "quotes", id = "<Copy the ID of your KV Store>" }
]
```

Then, we will update our worker with the code to store data in the KV store:

```jsx
export interface Env {
  quotes: KVNamespace;
}

export default {
  async fetch(
    request: Request,
    env: Env
  ): Promise<Response> {

    let url = new URL(request.url);
    
    switch (url.pathname) {
      case '/create':

	    // We generate a random key for your quote
        const id = crypto.randomUUID();
        
	    // We retrieve the quote you pass in your request body
        const quote = (await request.json() as any).quote;
        
        // We store your quote in the KV Store
        await env.quotes.put(
          id,
          quote
        );

        return new Response(
          JSON.stringify('Success'),
          {
            headers: {
              'content-type': 'application/json',
              'Access-Control-Allow-Headers': '*',
              'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
              'Access-Control-Allow-Origin': '*',
            },
          }
        );
		};
	}};
```

You can notice several things:

- We added an interface that refers to our `quotes` KV store. This allows us to directly interact with the store through the `env` parameter of the worker.
- We are retrieving the body of the request using `request.json()`
- We store the quote in KV using the `put` function, that takes a key and a value as parameters.

If you redeploy your worker using `wrangler` , call it with a POST request on the `/create` route, and a JSON payload containing a `quote` parameter, you should be able to store quotes in your KV store. You can check in your Cloudflare dashboard that it is indeed working 🚀 !


![Stored quote in KV](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fxcdvkybovcvxdwwfmdr.png)


## Retrieving random quotes

To wrap things up, we need to be able to retrieve random quotes from our worker. Let’s do that ! We will add a new `/get` route, that will return a random quote from our KV store. Just add a new `case` in the `switch`:

```jsx
case '/get':
    // We retrieve all the quotes keys
    const quotesKeys = (await env.quotes.list()).keys.map((key) => key.name);
		
    // We pick a random key, and retrieve it from the KV Store
    const randomId = quotesKeys[Math.floor(Math.random() * quotesKeys.length)]
    const randomQuote = await env.quotes.get(randomId, 'text');

    return new Response(
      randomQuote,
      {
        headers: {
          'content-type': 'application/json',
          'Access-Control-Allow-Headers': '*',
          'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
          'Access-Control-Allow-Origin': '*',
        },
      }
    );
```

In this code we are:

- Listing all the keys of our quotes stored in the KV store using the `list()` function,
- We are getting a quote from the KV store using the `get()` function

If you redeploy your Cloudflare Worker you should now be able to call the HTTP GET `/get` endpoint to retrieve a random quote 🎊 ! 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lk9d9hx9tscgljy5mdmc.gif)

## Conclusion

**Congratulations, you just created a worker to store and return random quotes !** If you want to push things further, you can plug a Slack bot on it for instance.

I hope you liked this article, don’t hesitate to ask the questions you have in the comments !