【Cloudflare】如何使用node.js开发 Cloudflare worker?

使用 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。
  • 开发方式: 我们使用 Node.js 的工具链(npm/yarn/pnpmwrangler CLI、TypeScript、ESLint、Bundlers)来编写和打包 Worker 代码,但代码本身要符合 Worker Runtime 的限制。
  • Wrangler: Cloudflare 官方的 CLI 工具,用于开发、测试、部署 Workers。它内置了强大的构建能力(基于 esbuild),能够处理 TypeScript、JSX、CommonJS/ESM 模块,并自动打包你的 Worker 代码及其依赖。

2. 前置准备

  1. 安装 Node.js 和 npm/yarn/pnpm: 确保你的机器上安装了 Node.js(推荐 LTS 版本),这将同时安装 npm。

  2. 安装 Wrangler CLI:

    bash 复制代码
    npm install -g wrangler
    # 或者使用 yarn
    # yarn global add wrangler
    # 或者使用 pnpm
    # pnpm install -g wrangler
  3. 登录 Cloudflare 账号:

    bash 复制代码
    wrangler 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: 提供对 waitUntilpassThroughOnException 的访问,用于在请求完成后继续执行异步任务或处理异常。
  • 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> 命令来设置。

    bash 复制代码
    wrangler 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 的类型定义。

    bash 复制代码
    npm install -D @cloudflare/workers-types
  • tsconfig.json 会自动生成,确保 target 设置为 es2022 或更高,lib 包含 esnextdom

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 存储):
    1. 创建 KV 命名空间:wrangler kv:namespace create my_kv_namespace (会得到一个 ID)
    2. 绑定到 Worker:在 wrangler.toml 中添加 [[kv_namespaces]] 配置。
    3. 在 Worker 代码中通过 env.MY_KV_NAMESPACE 访问。
  • Durable Objects: 用于构建有状态的服务。
    1. 定义 Durable Object 类。
    2. wrangler.toml 中添加 [[durable_objects.bindings]][[durable_objects.classes]] 配置。
    3. 通过 env.<BINDING_NAME>.get(id) 获取 Durable Object 实例。
  • R2 (对象存储):
    1. 创建 R2 存储桶。
    2. wrangler.toml 中添加 [[r2_buckets]] 配置。
    3. 通过 env.MY_R2_BUCKET 访问。
  • D1 (SQL 数据库):
    1. 创建 D1 数据库。
    2. wrangler.toml 中添加 [[d1_databases]] 配置。
    3. 通过 env.DB.prepare(...).run() 访问。
示例:在 Worker 中使用 KV
  1. 创建 KV 命名空间:

    bash 复制代码
    wrangler kv:namespace create MY_DATA
    # 记住输出的 ID
  2. 更新 wrangler.toml:

    toml 复制代码
    # ...
    [[kv_namespaces]]
    binding = "MY_DATA" # 你在 Worker 代码中引用的变量名 (env.MY_DATA)
    id = "YOUR_KV_NAMESPACE_ID_HERE" # 上一步创建时得到的 ID
  3. 更新 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.subtle API 而不是 Node.js 的 crypto 模块。
  • 性能优化:

    • 保持 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 startnpm run deploy 等命令执行。

通过遵循上述步骤和最佳实践,你可以充分利用 Node.js 生态系统的强大功能(如包管理、构建工具和 TypeScript)来高效开发和部署 Cloudflare Workers。

相关推荐
程序员爱钓鱼1 小时前
Node.js 编程实战:路径模块(path)详解
后端·node.js·trae
Q_Q51100828513 小时前
python+django/flask+vue的大健康养老公寓管理系统
spring boot·python·django·flask·node.js
老前端的功夫16 小时前
移动端兼容性深度解析:从像素到交互的全方位解决方案
前端·前端框架·node.js·交互·css3
Q_Q196328847517 小时前
python+django/flask+vue的多媒体素材管理系统
spring boot·python·django·flask·node.js·php
Q_Q51100828518 小时前
python+django/flask+vue的基于疫情防控管理系统的数据可视化分析系统
spring boot·python·django·flask·node.js
前端fighter19 小时前
全栈项目:闲置二手交易系统(二)
前端·vue.js·node.js
克里斯蒂亚诺更新1 天前
登录接口思路和开发
node.js
Q_Q5110082851 天前
python+django/flask医药垃圾分类管理系统
spring boot·python·django·flask·node.js·php
韩立学长1 天前
【开题答辩实录分享】以《基于Vue Node.js的露营场地管理系统的设计与实现》为例进行选题答辩实录分享
数据库·vue.js·node.js