Rspress on Cloudflare Workers

How to deploy rspress to cloudflare workers.

I had problems deploying this blog via cloudflare pages and so I switch to use cloudflare workers. This is a short guide how to setup rspress with cloudflare workers.

Setup a Rspress project

1pnpm create rspress@latest

Setup Cloudflare Workers

1pnpm add --save-dev wrangler @cloudflare/kv-asset-handler

Setup wrangler.toml

wrangler.toml
1compatibility_date = "2023-10-30"
2main = "src/index.ts" # The entry point for your Workers application
3name = "UNIQUE NAME" # Your project's name
4route = "https://blog.YOURDOMAIN.com/*" # The route to your Workers application
5
6[build]
7command = "npm run rs.build" # To preview the blog within the cloudflare workers environment,
8# create a npm script to run rspress build
9cwd = "." # Current working directory relative to wrangler.toml
10watch_dir = "./docs" # Your blogposts directory
11
12[site]
13bucket = "./doc_build" # Important to create a bucket for the static files

Setup package.json

For local development use rspress dev and to preview the blog with cloudflare workers enabled use wrangler dev. To deploy the blog use wrangler deploy.

package.json
1"scripts": {
2    "rs.dev": "rspress dev",
3    "rs.build": "rspress build",
4    "preview": "rspress preview",
5    "start": "rspress build && rspress preview",
6    "dev": "wrangler dev",
7    "deploy": "wrangler deploy"
8  },

Create index.ts

To handle the static files, we need to create a index.ts file in the src directory. So the cloudflare worker can handle the static files.

src/index.ts
1import { getAssetFromKV } from '@cloudflare/kv-asset-handler'
2// @ts-ignore
3import manifestJSON from '__STATIC_CONTENT_MANIFEST'
4const assetManifest = JSON.parse(manifestJSON)
5
6export default {
7  async fetch(request, env, ctx) {
8    try {
9      // Add logic to decide whether to serve an asset or run your original Worker code
10      return await getAssetFromKV(
11        {
12          request,
13          waitUntil: ctx.waitUntil.bind(ctx)
14        },
15        {
16          ASSET_NAMESPACE: env.__STATIC_CONTENT,
17          ASSET_MANIFEST: assetManifest
18        }
19      )
20    } catch (e) {
21      let pathname = new URL(request.url).pathname
22      return new Response(`"${pathname}" not found`, {
23        status: 404,
24        statusText: 'not found'
25      })
26    }
27  }
28}

Example this blog

If you want to see a production setup of this blog, you can check out the source code and the blog.