Cloudflare Workers

Cloudflare Workers 是运行在 Cloudflare CDN 上的 JavaScript 边缘运行时(edge runtime)。

你可以在本地开发应用,然后通过 Wrangler 使用几条命令即可发布。Wrangler 内置了转译器(trans compiler),因此我们可以直接用 TypeScript 编写代码。

接下来,让我们使用 Hono 为 Cloudflare Workers 创建你的第一个应用。

1. 安装

Cloudflare Workers 有现成的 Starter 模板。用 create-hono 命令启动项目。本例中选择 cloudflare-workers 模板。

npm

  1. npm create hono@latest my-app

yarn

  1. yarn create hono my-app

pnpm

  1. pnpm create hono@latest my-app

bun

  1. bun create hono@latest my-app

deno

  1. deno init --npm hono my-app

进入 my-app 目录并安装依赖。

npm

  1. cd my-app
  2. npm i

yarn

  1. cd my-app
  2. yarn

pnpm

  1. cd my-app
  2. pnpm i

bun

  1. cd my-app
  2. bun i

2. Hello World

编辑 src/index.ts

  1. import { Hono } from 'hono'
  2. const app = new Hono()
  3. app.get('/', (c) => c.text('Hello Cloudflare Workers!'))
  4. export default app

3. 运行

本地运行开发服务器,然后在浏览器访问 http://localhost:8787

npm

  1. npm run dev

yarn

  1. yarn dev

pnpm

  1. pnpm dev

bun

  1. bun run dev

修改端口号

如果需要更改端口号,可以编辑 wrangler.toml / wrangler.json / wrangler.jsonc 文件,参考:Wrangler Configuration

也可以通过 CLI 选项设置,参考:Wrangler CLI

4. 部署

如果你有 Cloudflare 账号,可以将应用部署到 Cloudflare。在 package.json 中,将 $npm_execpath 改成你使用的包管理器。

npm

  1. npm run deploy

yarn

  1. yarn deploy

pnpm

  1. pnpm run deploy

bun

  1. bun run deploy

就是这么简单!

Service Worker 模式 vs Module Worker 模式

Cloudflare Workers 有两种写法:Module Worker modeService Worker mode。使用 Hono 可以兼容两种写法,但推荐使用 Module Worker mode,因为绑定变量会被局部化。

  1. // Module Worker
  2. export default app
  1. // Service Worker
  2. app.fire()

与其他事件处理器一起使用

Module Worker mode 中,可以将 Hono 与其他事件处理器(如 scheduled)结合使用。

  1. const app = new Hono()
  2. export default {
  3. fetch: app.fetch,
  4. scheduled: async (batch, env) => {},
  5. }

服务静态文件

如果需要提供静态文件服务,可以使用 Cloudflare Workers 的 Static Assets 功能。在 wrangler.toml 指定目录:

  1. assets = { directory = "public" }

然后创建 public 目录并放置文件。例如,./public/static/hello.txt 将被映射为 /static/hello.txt

  1. .
  2. ├── package.json
  3. ├── public
  4. ├── favicon.ico
  5. └── static
  6. └── hello.txt
  7. ├── src
  8. └── index.ts
  9. └── wrangler.toml

类型支持

如果想要 Workers 类型,需要安装 @cloudflare/workers-types

npm

  1. npm i --save-dev @cloudflare/workers-types

yarn

  1. yarn add -D @cloudflare/workers-types

pnpm

  1. pnpm add -D @cloudflare/workers-types

bun

  1. bun add --dev @cloudflare/workers-types

测试

测试推荐使用 @cloudflare/vitest-pool-workers。可参考 examples 进行设置。

示例应用:

  1. import { Hono } from 'hono'
  2. const app = new Hono()
  3. app.get('/', (c) => c.text('Please test me!'))

我们可以测试它是否返回 200 OK

  1. describe('Test the application', () => {
  2. it('Should return 200 response', async () => {
  3. const res = await app.request('http://localhost/')
  4. expect(res.status).toBe(200)
  5. })
  6. })

Bindings(绑定)

在 Cloudflare Workers 中,可以绑定环境变量、KV namespace、R2 bucket 或 Durable Object。可通过 c.env 访问它们。如果将 “type struct“ 作为泛型传给 Hono,还会自动获得类型提示。

  1. type Bindings = {
  2. MY_BUCKET: R2Bucket
  3. USERNAME: string
  4. PASSWORD: string
  5. }
  6. const app = new Hono<{ Bindings: Bindings }>()
  7. app.put('/upload/:key', async (c, next) => {
  8. const key = c.req.param('key')
  9. await c.env.MY_BUCKET.put(key, c.req.body)
  10. return c.text(`Put ${key} successfully!`)
  11. })

在 Middleware 中使用变量

仅适用于 Module Worker mode。如果需要在 Middleware 中使用变量或密钥变量(如 Basic Authentication 的 usernamepassword),写法如下:

  1. import { basicAuth } from 'hono/basic-auth'
  2. type Bindings = {
  3. USERNAME: string
  4. PASSWORD: string
  5. }
  6. const app = new Hono<{ Bindings: Bindings }>()
  7. app.use('/auth/*', async (c, next) => {
  8. const auth = basicAuth({
  9. username: c.env.USERNAME,
  10. password: c.env.PASSWORD,
  11. })
  12. return auth(c, next)
  13. })

同样适用于 Bearer Authentication、JWT Authentication 等。

从 GitHub Actions 部署

通过 CI 部署到 Cloudflare 前,需要一个 Cloudflare token。可在 User API Tokens 管理。

新建 token 时选择 Edit Cloudflare Workers 模板;已有 token 时确保其具有相应权限(Cloudflare Pages 和 Workers 的 token 权限不共享)。

然后在 GitHub 仓库设置中添加 CLOUDFLARE_API_TOKEN 到:Settings -> Secrets and variables -> Actions -> Repository secrets

接着在项目根目录创建 .github/workflows/deploy.yml

  1. name: Deploy
  2. on:
  3. push:
  4. branches:
  5. - main
  6. jobs:
  7. deploy:
  8. runs-on: ubuntu-latest
  9. name: Deploy
  10. steps:
  11. - uses: actions/checkout@v4
  12. - name: Deploy
  13. uses: cloudflare/wrangler-action@v3
  14. with:
  15. apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}

编辑 wrangler.toml,在 compatibility_date 之后添加:

  1. main = "src/index.ts"
  2. minify = true

一切就绪!推送代码即可。

本地开发加载环境变量

本地开发时,可以在项目根目录创建 .dev.vars 文件,并像普通 .env 文件一样配置:

  1. SECRET_KEY=value
  2. API_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

更多信息可参考 Cloudflare 文档: https://developers.cloudflare.com/workers/wrangler/configuration/#secrets

然后通过 c.env.* 获取变量。 注意:在 Cloudflare Workers 中必须通过 c 获取环境变量,而不是 process.env

  1. type Bindings = {
  2. SECRET_KEY: string
  3. }
  4. const app = new Hono<{ Bindings: Bindings }>()
  5. app.get('/env', (c) => {
  6. const SECRET_KEY = c.env.SECRET_KEY
  7. return c.text(SECRET_KEY)
  8. })

在部署到 Cloudflare 之前,记得在 Cloudflare Workers 项目配置中设置环境变量/密钥。

详情见:https://developers.cloudflare.com/workers/configuration/environment-variables/#add-environment-variables-via-the-dashboard