使用 Node.js 开发 Cloudflare Worker 主要是指利用 Node.js 的生态系统 (如 npm 包管理器、构建工具、TypeScript 支持等)来编写和管理 Worker 代码。需要特别注意的是,Cloudflare Workers 运行在 V8 引擎的 isolates 中,它不是 Node.js 运行时环境 。这意味着你不能直接使用 Node.js 的内置模块(如 fs, path, http 等),但你可以使用 npm 安装的绝大部分纯 JavaScript 库(只要它们不依赖 Node.js 特有的 API)。
以下是使用 Node.js 生态系统开发 Cloudflare Worker 的详细步骤和最佳实践:
1. 核心概念理解
- Workers Runtime vs. Node.js Runtime:
- Workers Runtime: 极速启动、低内存占用、基于 Web 标准 API(
fetch,URL,TextEncoder等)。不支持 Node.js 内置模块。 - Node.js Runtime: 提供了丰富的文件系统、网络、进程管理等 API。
- Workers Runtime: 极速启动、低内存占用、基于 Web 标准 API(
- 开发方式: 我们使用 Node.js 的工具链(
npm/yarn/pnpm、wranglerCLI、TypeScript、ESLint、Bundlers)来编写和打包 Worker 代码,但代码本身要符合 Worker Runtime 的限制。 - Wrangler: Cloudflare 官方的 CLI 工具,用于开发、测试、部署 Workers。它内置了强大的构建能力(基于 esbuild),能够处理 TypeScript、JSX、CommonJS/ESM 模块,并自动打包你的 Worker 代码及其依赖。
2. 前置准备
-
安装 Node.js 和 npm/yarn/pnpm: 确保你的机器上安装了 Node.js(推荐 LTS 版本),这将同时安装 npm。
-
安装 Wrangler CLI:
bashnpm install -g wrangler # 或者使用 yarn # yarn global add wrangler # 或者使用 pnpm # pnpm install -g wrangler -
登录 Cloudflare 账号:
bashwrangler login这会在浏览器中打开一个页面,允许你授权 Wrangler 访问你的 Cloudflare 账号。
3. 创建和开发 Worker
步骤 1: 初始化 Worker 项目
你可以使用 wrangler init 命令快速创建一个新的 Worker 项目。
bash
wrangler init my-worker-app --type=webpack # 或 --type=simple, --type=rust, --type=honos 等
# 推荐使用默认的 `simple` 或 `webpack` 类型,因为它们最适合 JS/TS
# 如果你计划使用 TypeScript,wrangler init 会自动为你配置好
--type=webpack: 创建一个使用 webpack 进行打包的 Worker 项目(如果你需要更复杂的构建配置,例如对 CSS 或其他资产的处理)。- 默认 (或
--type=simple): 创建一个只包含基本 Worker 代码和wrangler.toml配置的简单项目。Wrangler 仍然会使用其内置的 esbuild 编译器来处理你的 JS/TS 文件和依赖。对于大多数情况,这已经足够且更快。
我们以默认(或 simple 类型)为例:
bash
wrangler init my-worker-app
# 回答提示问题:
# Would you like to use TypeScript? (y/N) Y # 推荐使用 TypeScript
# Would you like to use Git for version control? (y/N) Y
# Would you like to deploy your application? (y/N) N # 暂时不部署
这会创建一个名为 my-worker-app 的文件夹,其中包含:
src/index.ts(或src/index.js): Worker 的入口文件。wrangler.toml: Worker 的配置文件。package.json: Node.js 项目的配置文件,用于管理依赖和脚本。tsconfig.json(如果选择了 TypeScript): TypeScript 配置文件。
步骤 2: 编写 Worker 代码 (src/index.ts)
打开 src/index.ts(或 src/index.js),你会看到一个基本的 Worker 结构。
typescript
// src/index.ts
export interface Env {
MY_VARIABLE: string;
MY_SECRET: string;
MY_KV_NAMESPACE: KVNamespace; // 如果你有 KV 绑定
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === '/hello') {
return new Response(`Hello from Cloudflare Worker! MY_VARIABLE: ${env.MY_VARIABLE}`, {
headers: { 'content-type': 'text/plain' },
});
}
if (url.pathname === '/secret') {
// 访问绑定的 secret 变量
return new Response(`Your secret is: ${env.MY_SECRET}`, {
headers: { 'content-type': 'text/plain' },
});
}
// 默认响应
return new Response('Welcome to my Worker!', {
headers: { 'content-type': 'text/plain' },
});
},
};
关键点:
export default { fetch(...) }: 这是 Worker 的标准入口点,它监听fetch事件。Request: 传入的请求对象,符合 Web Request API。env: 一个对象,包含所有通过wrangler.toml或 secrets 绑定的环境变量和资源(如 KV 命名空间、Durable Objects 等)。ExecutionContext: 提供对waitUntil和passThroughOnException的访问,用于在请求完成后继续执行异步任务或处理异常。Response: 返回的响应对象,符合 Web Response API。
步骤 3: 配置 wrangler.toml
wrangler.toml 是 Worker 的核心配置文件。
toml
name = "my-worker-app" # Worker 名称
main = "src/index.ts" # Worker 入口文件
compatibility_date = "2023-10-26" # 兼容性日期,使用最新日期以获得最新特性
# 环境变量 (公开)
[vars]
MY_VARIABLE = "这是一个公开变量"
# KV 命名空间绑定 (如果需要)
# [[kv_namespaces]]
# binding = "MY_KV_NAMESPACE"
# id = "YOUR_KV_NAMESPACE_ID" # 通过 `wrangler kv:namespace create` 获取
# R2 存储桶绑定 (如果需要)
# [[r2_buckets]]
# binding = "MY_R2_BUCKET"
# bucket_name = "your-r2-bucket-name"
# D1 数据库绑定 (如果需要)
# [[d1_databases]]
# binding = "DB"
# database_name = "your-d1-database-name"
# database_id = "your-d1-database-id"
-
name: Worker 的名称。 -
main: Worker 的入口文件路径(Wrangler 会自动处理.ts或.js)。 -
compatibility_date: 非常重要。设置一个最新的日期以确保你的 Worker 运行在最新的运行时版本上,从而获得最新的特性和性能改进。 -
[vars]: 定义公共环境变量,可以在 Worker 代码中通过env.VAR_NAME访问。 -
Secrets: 对于敏感信息(如 API 密钥),不应放在
wrangler.toml中。使用wrangler secret put <SECRET_NAME>命令来设置。bashwrangler secret put MY_SECRET # 提示输入 secret 值然后,你可以在 Worker 代码中通过
env.MY_SECRET访问它。
步骤 4: 安装和使用 Node.js 依赖
你可以像常规 Node.js 项目一样安装任何纯 JavaScript 包。
bash
npm install nanoid @ts-rest/core
# 或者 yarn add nanoid @ts-rest/core
# 或者 pnpm add nanoid @ts-rest/core
然后在 src/index.ts 中导入并使用它们:
typescript
// src/index.ts
import { nanoid } from 'nanoid';
// ... (其他代码)
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === '/generate-id') {
const id = nanoid();
return new Response(`Generated ID: ${id}`, {
headers: { 'content-type': 'text/plain' },
});
}
// ...
},
};
Wrangler 会在打包时自动识别并打包这些依赖,将其包含在最终的 Worker 脚本中。
5. 本地开发和测试
使用 wrangler dev 命令在本地模拟 Worker 运行环境:
bash
wrangler dev
这会在本地启动一个开发服务器,通常在 http://localhost:8787。你可以在浏览器中访问它,或者使用 curl 进行测试。Wrangler 会自动监听文件变化并热重载。
- 访问
http://localhost:8787/hello - 访问
http://localhost:8787/secret - 访问
http://localhost:8787/generate-id
6. 部署 Worker
当你的 Worker 开发完毕并通过测试后,可以将其部署到 Cloudflare:
bash
wrangler deploy
Wrangler 会将你的代码打包并上传到 Cloudflare。部署成功后,它会告诉你 Worker 的 URL。
4. 高级开发实践
TypeScript 支持
如上所示,wrangler init 选择 TypeScript 会自动配置。Wrangler 内置支持 TypeScript,无需额外配置 Webpack 或 Babel。
-
类型声明: 安装
@cloudflare/workers-types以获取 Worker API 的类型定义。bashnpm install -D @cloudflare/workers-types -
tsconfig.json会自动生成,确保target设置为es2022或更高,lib包含esnext和dom。
Bundling (打包)
Wrangler 默认使用 esbuild 进行打包。这意味着你可以在代码中使用 ES Modules (import/export) 语法,即使你的依赖是 CommonJS 格式,esbuild 也会正确处理它们。
环境变量和 Secrets
-
wrangler.toml[vars]: 用于非敏感的配置值。在开发和生产环境中都可以被 Worker 访问。 -
wrangler secret put <NAME>: 用于敏感信息(API 密钥、数据库凭据等)。这些值在 Cloudflare 基础设施中加密存储,并且只在运行时注入到 Worker 环境中。 -
本地使用 Secrets:
wrangler dev默认会尝试从.dev.vars文件中读取同名的秘密变量。
创建一个.dev.vars文件:# .dev.vars MY_SECRET="my_local_dev_secret_value"注意:将
.dev.vars添加到.gitignore中,不要提交到版本控制!
绑定资源
- KV 命名空间 (Key-Value 存储):
- 创建 KV 命名空间:
wrangler kv:namespace create my_kv_namespace(会得到一个 ID) - 绑定到 Worker:在
wrangler.toml中添加[[kv_namespaces]]配置。 - 在 Worker 代码中通过
env.MY_KV_NAMESPACE访问。
- 创建 KV 命名空间:
- Durable Objects: 用于构建有状态的服务。
- 定义 Durable Object 类。
- 在
wrangler.toml中添加[[durable_objects.bindings]]和[[durable_objects.classes]]配置。 - 通过
env.<BINDING_NAME>.get(id)获取 Durable Object 实例。
- R2 (对象存储):
- 创建 R2 存储桶。
- 在
wrangler.toml中添加[[r2_buckets]]配置。 - 通过
env.MY_R2_BUCKET访问。
- D1 (SQL 数据库):
- 创建 D1 数据库。
- 在
wrangler.toml中添加[[d1_databases]]配置。 - 通过
env.DB.prepare(...).run()访问。
示例:在 Worker 中使用 KV
-
创建 KV 命名空间:
bashwrangler kv:namespace create MY_DATA # 记住输出的 ID -
更新
wrangler.toml:toml# ... [[kv_namespaces]] binding = "MY_DATA" # 你在 Worker 代码中引用的变量名 (env.MY_DATA) id = "YOUR_KV_NAMESPACE_ID_HERE" # 上一步创建时得到的 ID -
更新
src/index.ts:typescript// src/index.ts export interface Env { MY_DATA: KVNamespace; // 声明 KV 命名空间的类型 } export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { const url = new URL(request.url); if (url.pathname === '/put') { const key = url.searchParams.get('key'); const value = url.searchParams.get('value'); if (key && value) { await env.MY_DATA.put(key, value); return new Response(`Stored: ${key} = ${value}`); } return new Response('Missing key or value', { status: 400 }); } if (url.pathname === '/get') { const key = url.searchParams.get('key'); if (key) { const value = await env.MY_DATA.get(key); if (value) { return new Response(`Value for ${key}: ${value}`); } return new Response(`Key ${key} not found`, { status: 404 }); } return new Response('Missing key', { status: 400 }); } return new Response('Welcome to my Worker!'); }, };
5. 注意事项和最佳实践
-
无
node_modules文件夹: 部署时,Worker 不会包含node_modules文件夹。所有的第三方依赖都会被打包工具(esbuild)编译进一个单独的 JavaScript 文件中。 -
避免 Node.js 内置模块: 再次强调,不要尝试使用
require('fs')、require('path')、require('http')等。如果需要类似功能,寻找 Web API 替代品或专门为 Workers 设计的库。- 例如,处理 URL 使用
new URL()对象而不是path模块。 - 加密操作使用
crypto.subtleAPI 而不是 Node.js 的crypto模块。
- 例如,处理 URL 使用
-
性能优化:
- 保持 Worker 脚本体积小巧,避免不必要的依赖。
- 利用
ctx.waitUntil()处理不影响主响应的异步任务(例如记录日志、发送分析数据)。 - 尽可能使用 Cloudflare 提供的绑定(KV, R2, D1, Durable Objects),它们通常比外部服务更快且更便宜。
-
错误处理: 使用
try...catch块来捕获异步操作中的错误,并返回适当的错误响应。 -
TypeScript 优势: 强烈建议使用 TypeScript,它能提供更好的代码可维护性、自动补全和错误检查。
-
package.json脚本: 可以在package.json中定义常用的脚本,例如:json// package.json "scripts": { "start": "wrangler dev", "deploy": "wrangler deploy", "test": "vitest" // 如果使用 vitest 等测试框架 },然后通过
npm start、npm run deploy等命令执行。
通过遵循上述步骤和最佳实践,你可以充分利用 Node.js 生态系统的强大功能(如包管理、构建工具和 TypeScript)来高效开发和部署 Cloudflare Workers。