Cloudflare

将 Nitro 应用部署到 Cloudflare。

#Cloudflare Workers

预设: cloudflare_module

Read more in Cloudflare Workers.

Note

通过与该提供商的集成支持 workers builds (beta),可以实现零配置。

下面展示了用于将 Nitro 应用部署到 Cloudflare Workers 的示例 nitro.config.ts 文件。

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
    preset: "cloudflare_module"
})

#本地预览

你可以使用 Wrangler 在本地预览你的应用:

npm run build
npx wrangler dev

#手动部署

构建应用后,你可以使用 Wrangler 手动部署。

首先确保你已登录到你的 Cloudflare 账户:

npx wrangler login

然后你可以使用以下命令部署应用:

npx wrangler deploy

#运行时钩子

你可以使用下面的运行时钩子来扩展 Worker 处理程序。

Read more in Docs > Plugins#nitro Runtime Hooks.

Note

cloudflare:queue 钩子通过 batch 接收消息批次,cloudflare:email 钩子通过 message 接收传入的消息。

#Durable Objects

从 server.ts 文件导出 Durable Object 类。它们在部署后的 Worker 和本地开发环境(包括 Vite)中都可用。也可以在其他文件中定义这些类,再从此处重新导出。

server.ts
import { DurableObject } from "cloudflare:workers";

export class Counter extends DurableObject {
  async fetch() {
    const count = (await this.ctx.storage.get<number>("count")) || 0;
    await this.ctx.storage.put("count", count + 1);
    return Response.json({ count: count + 1 });
  }
}

export default {
  fetch() {},
};

Note

server.ts 必须包含默认导出。如果该文件仅用于导出 Durable Objects,请保留上面的空 fetch 处理器,以便请求继续交由你的路由处理。

在 Wrangler 配置中声明绑定和 Durable Object 导出:

wrangler.json
{
  "durable_objects": {
    "bindings": [{ "name": "COUNTER", "class_name": "Counter" }]
  },
  "exports": {
    "Counter": { "type": "durable-object", "storage": "sqlite" }
  }
}

在 Nitro 处理器中访问该绑定:

routes/counter.ts
import { defineHandler } from "nitro";

export default defineHandler((event) => {
  const { COUNTER } = event.req.runtime!.cloudflare!.env;
  return COUNTER.get(COUNTER.idFromName("default")).fetch(event.req);
});

使用 Wrangler 环境时,请在所选环境中声明绑定和导出。本地 Durable Object 状态会保存在 .wrangler/state/v3 中,包括开发服务器重新加载前后的状态。

在开发环境中,Durable Objects 会与路由共享模块状态,并在开发服务器不重启的情况下应用代码更改。新增的类或未在 Wrangler 配置中声明的类会触发警告。

如需使用 Counter 类为 COUNTER 绑定添加类型,请参阅绑定类型。

#额外导出

Workflows 或 WorkerEntrypoint 等其他类也以相同方式从 server.ts 导出:

server.ts
import {
  WorkerEntrypoint,
  WorkflowEntrypoint,
  type WorkflowEvent,
  type WorkflowStep,
} from "cloudflare:workers";

export class MyWorkflow extends WorkflowEntrypoint {
  async run(event: WorkflowEvent, step: WorkflowStep) {
    // ...
  }
}

export class MyEntrypoint extends WorkerEntrypoint {
  greet(name: string) {
    return `Hello ${name}`;
  }
}

在 Wrangler 配置中通过 workflows 绑定或 exports 条目声明这些类:

wrangler.json
{
  "workflows": [{ "name": "my-workflow", "binding": "MY_WORKFLOW", "class_name": "MyWorkflow" }],
  "exports": {
    "MyEntrypoint": { "type": "worker" }
  }
}

#定时任务(Cron 触发器)

当使用带有 scheduledTasks 的 Nitro 任务时,Nitro 会在构建时自动在 wrangler 配置中生成 Cron 触发器。

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  preset: "cloudflare_module",
  experimental: {
    tasks: true,
  },
  scheduledTasks: {
    "* * * * *": ["cms:update"],
    "0 15 1 * *": ["db:cleanup"],
  }
})

无需手动配置 Wrangler,Nitro 会为你处理。

#Cloudflare Workers with Durable Objects

预设: cloudflare_durable

Read more in Durable Objects.

此预设扩展了 cloudflare_module,并通过 Durable Object 实例路由请求,从而支持有状态功能,例如 WebSocket 支持(通过 CrossWS)以及可跨请求持久存在的内存状态。

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  preset: "cloudflare_durable"
})

预设入口会导出 $DurableObject 类。在 Wrangler 配置中声明其绑定和导出:

wrangler.json
{
  "durable_objects": {
    "bindings": [
      {
        "name": "$DurableObject",
        "class_name": "$DurableObject"
      }
    ]
  },
  "exports": {
    "$DurableObject": { "type": "durable-object", "storage": "sqlite" }
  }
}

你可以使用 cloudflare:durable:init 运行时钩子,在 Durable Object 初始化时运行代码,并使用 cloudflare:durable:alarm 钩子处理 alarms。

#追踪

🧪 实验性功能!

启用实验性的 tracingChannel 选项后,Cloudflare 预设会将 Nitro 的追踪通道事件(h3 路由和中间件、srvx、unstorage 操作等)作为自定义 span进行报告,同时还会报告 Cloudflare 的自动插桩事件(fetch 调用、KV 读取、D1 查询等),无需 OpenTelemetry SDK。

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  preset: "cloudflare_module",
  tracingChannel: true,
});

必须在 Worker 上启用追踪,才能记录 span:

wrangler.jsonc
{
  "observability": {
    "traces": {
      "enabled": true
    }
  }
}

#Cloudflare Pages

预设: cloudflare_pages

Read more in Cloudflare Pages.

Note

与该提供商的集成支持零配置。

Warning

Cloudflare Workers 是目前推荐用于部署的新预设。如果你需要 Pages 特有的功能,请考虑使用 Cloudflare Pages。

以下展示了用于将 Nitro 应用部署到 Cloudflare Pages 的示例 nitro.config.ts 文件。

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
    preset: "cloudflare_pages"
})

Nitro 自动生成一个 _routes.json 文件,用于控制哪些路由由文件提供,哪些由 Worker 脚本提供。自动生成的路由文件可以通过配置选项 cloudflare.pages.routes 覆盖(了解更多)。

#本地预览

你可以使用 Wrangler 在本地预览你的应用:

npm run build
npx wrangler pages dev

#手动部署

构建应用后,你可以使用 Wrangler 手动部署。

首先确保你已登录到你的 Cloudflare 账户:

npx wrangler login

然后你可以使用以下命令部署应用:

npx wrangler pages deploy

#使用 GitHub Actions 在 CI/CD 中部署

无论你使用的是 Cloudflare Pages 还是 Cloudflare Workers,都可以使用 Wrangler GitHub actions 来部署应用。

Note

请记得指示 Nitro 使用正确的预设。所有预设都需要这样做,包括 cloudflare_pages。

#环境变量

Nitro 允许你通过 process.env、import.meta.env 或运行时配置,以统一的方式访问环境变量。

Note

请确保只在事件生命周期内访问环境变量,而不要在全局上下文中访问,因为 Cloudflare 只会在请求生命周期内提供这些变量,而不会在此之前提供。

**示例:**如果你已设置 SECRET 和 NITRO_HELLO_THERE 环境变量,可以通过以下方式访问它们:

import { defineHandler } from "nitro";
import { useRuntimeConfig } from "nitro/runtime-config";

console.log(process.env.SECRET) // 注意:这里位于全局作用域!因此它实际上不会生效,变量会是 undefined!

export default defineHandler((event) => {
  // 注意:下面这些方式都可以访问上面的变量
  useRuntimeConfig().helloThere
  useRuntimeConfig().secret
  process.env.NITRO_HELLO_THERE
  import.meta.env.SECRET
});

#在开发模式中指定变量

对于开发,你可以使用 .env 或 .env.local 文件来指定环境变量:

NITRO_HELLO_THERE="captain"
SECRET="top-secret"

Note

请确保将 .env 和 .env.local 添加到 .gitignore 文件中,以免提交它们,因为其中可能包含敏感信息。

#为本地预览指定变量

构建完成后,当你使用 wrangler dev 或 wrangler pages dev 在本地试用项目时,请在项目根目录的 .dev.vars 文件中指定环境变量(如 Pages 和 Workers 文档中所述)。

如果你在开发时使用 .env 或 .env.local 文件,你的 .dev.vars 应该与之一致。

Note

请确保将 .dev.vars 添加到 .gitignore 文件中,以免提交它,因为其中可能包含敏感信息。

#为生产环境指定变量

对于生产环境,请使用 Cloudflare 仪表板或 wrangler secret 命令来设置环境变量和密钥。

#使用 wrangler.toml/wrangler.json 指定变量

你可以指定自定义的 wrangler.toml/wrangler.json 文件并在其中定义变量。

Warning

不建议使用此方式存储密钥等敏感数据。

示例:

# 共享
[vars]
NITRO_HELLO_THERE="general"
SECRET="secret"

# 为 `--env production` 用法覆盖值
[env.production.vars]
NITRO_HELLO_THERE="captain"
SECRET="top-secret"

#直接访问 Cloudflare 绑定

绑定允许你与 Cloudflare 平台中的资源进行交互,例如键值数据存储(KV)和无服务器 SQL 数据库(D1)。

Read more in .

Tip

Nitro 为 KV Storage 和 Database 等基础功能提供了高级 API。为了保持使用稳定性,优先使用这些 API,而不是直接依赖底层平台 API。

Read more in 数据库层.
Read more in KV 存储.

你可以通过 event.req.runtime.cloudflare.env 从请求事件中访问绑定。例如,以下是访问 D1 绑定的方式:

import { defineHandler } from "nitro";

defineHandler(async (event) => {
  const { env } = event.req.runtime.cloudflare
  const stmt = await env.MY_D1.prepare('SELECT id FROM table')
  const { results } = await stmt.all()
})

#绑定类型

使用 wrangler types 根据 Wrangler 配置为绑定和 Workers 运行时生成类型。该命令会写入 worker-configuration.d.ts 文件,并在其中声明全局 Env 接口。

package.json
{
  "scripts": {
    "postinstall": "wrangler types",
    "typecheck": "wrangler types && tsc --noEmit"
  }
}

在 tsconfig.json 中包含生成的文件。该文件也提供运行时类型,因此无需安装 @cloudflare/workers-types。Nitro 会为你启用 nodejs_compat 标记;如果还要使用 Node.js API,请将 @types/node(以及 wrangler)添加到开发依赖中,并在类型配置中加入 node:

tsconfig.json
{
  "compilerOptions": {
    "types": ["./worker-configuration.d.ts", "node"]
  }
}

从 cloudflare:workers 导入的绑定会自动获得类型:

import { defineHandler } from "nitro";
import { env } from "cloudflare:workers";

export default defineHandler(async () => {
  return env.MY_KV.get("key");
});

如需同时为 event.req.runtime.cloudflare.env 添加类型,请扩展 srvx 的 CloudflareEnv 接口:

env.d.ts
declare module "srvx" {
  interface CloudflareEnv extends Env {}
}

export {};

Note

要应用此扩展,项目必须能够解析 srvx。使用 pnpm 时,请将它添加到开发依赖中。

若要使用类为自定义 Durable Objects、Workflows 和 WorkerEntrypoint 绑定添加类型,请将 Wrangler 配置中的 main 指向导出这些类的文件。Nitro 仍会在生成的配置中将 main 设置为构建后的入口。

wrangler.json
{
  "main": "./server.ts"
}

之后,wrangler types 会从该文件读取这些类:

worker-configuration.d.ts
interface Env {
  COUNTER: DurableObjectNamespace<import("./server").Counter>;
  MY_WORKFLOW: Workflow<Parameters<import("./server").MyWorkflow["run"]>[0]["payload"]>;
  API: Service<typeof import("./server").Api>;
}

Tip

更改 Wrangler 配置后,请重新运行 wrangler types;也可以在 CI 中运行 wrangler types --check,以发现过期的类型。

#在本地开发中访问绑定

在开发模式下,Nitro 使用 Miniflare 模拟 Cloudflare 环境(这是 Wrangler 和生产环境中的 Cloudflare Workers 使用的相同 workerd 运行时)。这意味着绑定可以直接从请求事件中原生访问,无需单独的代理。

miniflare 软件包由你的项目负责管理:Nitro 会从你的 node_modules 中解析它,并在首次使用时提供安装选项。

要在开发模式下访问绑定,请先定义绑定。你可以在 wrangler.jsonc/wrangler.json/wrangler.toml 文件中完成此操作(读取 wrangler.jsonc、wrangler.toml 和 .dev.vars 需要安装 wrangler 软件包):

[vars]
MY_VARIABLE="my-value"

[[kv_namespaces]]
binding = "MY_KV"
id = "xxx"

或者,你也可以在 nitro.config.ts 中使用 cloudflare.wrangler 选项内联定义绑定(它接受与 wrangler.json 相同的结构):

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  preset: "cloudflare_module",
  cloudflare: {
    wrangler: {
      vars: {
        MY_VARIABLE: "my-value",
      },
      kv_namespaces: [{ binding: "MY_KV", id: "xxx" }],
    },
  },
})

从现在开始,运行

npm run dev

时,你可以按照上面的示例从请求事件中访问 MY_VARIABLE 和 MY_KV。

与 wrangler dev 相比,有以下几点不同:

  • 绑定(KV、D1、R2 等)的本地数据会持久化到 .wrangler/state/v3,并与 wrangler dev 共享。
  • 无论 compatibility_date 如何设置,都会使用已安装的 miniflare 所支持的最新兼容性日期。
  • Nitro 会提供静态资源。可使用从 server.ts 导出的本地 Durable Objects、Workflows 和 WorkerEntrypoint;但无法使用指向其他 Worker 的绑定(services、tail_consumers、外部 Durable Objects 和 Workflows)以及队列消费者。
  • 设置 cloudflare.wrangler 后,它会与最近的 Wrangler 配置文件合并。

#Wrangler environments

如果你有多个 Wrangler 环境,你可以使用 cloudflare.wranglerEnv 选项指定在本地开发模拟时要使用的环境:

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  preset: 'cloudflare_module',
  cloudflare: {
    wranglerEnv: 'preview'
  }
})