Chapter 02

第一个 Worker:wrangler + Hono

npm create cloudflarewrangler deploy 上线一共 10 行命令。本章把整个工程骨架、路由、环境、部署、日志全部走一遍,读完就能产出一个能被朋友用上的 API。

安装与登录

# Node 18+ 即可
npm install -g wrangler

# 登录(浏览器打开授权)
wrangler login

# 验证
wrangler whoami
#  getting user info...
#  you are logged in as: you@example.com

初始化项目

npm create cloudflare@latest my-api
#  选项:
#  - application: Hello World example
#  - language: TypeScript
#  - framework: Hono  ← 推荐
#  - git: yes
#  - deploy: no(先本地跑)

cd my-api
npm run dev

打开 http://localhost:8787,返回 Hello Hono!——但这不是普通的 Node 服务器,是 workerd(Cloudflare 的本地 Workers 模拟器),行为、API 与生产完全一致。

工程结构

my-api/
├── src/
│   └── index.ts          ← 入口
├── wrangler.toml         ← 配置(name, bindings, routes)
├── package.json
├── tsconfig.json
└── worker-configuration.d.ts  ← bindings 类型自动生成

基础 Worker:纯 fetch handler

export interface Env {
  // bindings 在这里声明(后面章节添加)
}

export default {
  async fetch(req: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(req.url);
    if (url.pathname === '/health') {
      return new Response('ok');
    }
    return new Response('hello ' + url.pathname);
  },
} satisfies ExportedHandler<Env>;

最小心智负担:给一个 Request,返回一个 Response。没有 Express、没有中间件栈,就是 Web 标准。

用 Hono 写路由

原生 if-else 写三个路由还行,再多就乱。Hono 是为 Workers 设计的超轻量框架(类型很棒,20KB):

import { Hono } from 'hono';
import { logger } from 'hono/logger';
import { cors } from 'hono/cors';

type Bindings = { /* 后面填 */ };

const app = new Hono<{ Bindings: Bindings }>();

app.use('*', logger());
app.use('/api/*', cors());

app.get('/', (c) => c.text('hello'));

app.get('/api/user/:id', (c) => {
  const id = c.req.param('id');
  return c.json({ id, name: 'Alice' });
});

app.post('/api/echo', async (c) => {
  const body = await c.req.json();
  return c.json({ you_sent: body });
});

export default app;

wrangler.toml 基础

name = "my-api"
main = "src/index.ts"
compatibility_date = "2026-05-01"
compatibility_flags = ["nodejs_compat"]

# 环境变量(非敏感)
[vars]
LOG_LEVEL = "info"
FEATURE_X = "true"

# 多环境
[env.production]
name = "my-api-prod"
routes = ["api.example.com/*"]

[env.staging]
name = "my-api-staging"
routes = ["api-staging.example.com/*"]
compatibility_date
Workers 的"兼容性年份"。更新这个日期意味着接受那之前的 API 语义变更,是一个可控升级开关。
compatibility_flags
单独启用某些特性,比如 nodejs_compat 允许用 Node 内置模块(Buffer、crypto、path 等)。
routes
绑定自己的域名。你域名需要先在 Cloudflare 托管 DNS,然后 wrangler deploy 自动绑定。

环境变量 vs Secrets

类型位置适合
[vars]wrangler.toml(明文,进 Git)功能开关、非敏感常量
Secretwrangler secret put(加密存储)API key、数据库密码
wrangler secret put OPENAI_KEY
# 提示输入,然后存入加密后台

# 代码里同样通过 env 访问
# c.env.OPENAI_KEY

重要:secret 不会出现在 wrangler.toml。多环境时用 wrangler secret put OPENAI_KEY --env production

本地开发

npm run dev
# [wrangler:inf] Ready on http://localhost:8787

# 带远程 bindings(读真实 KV / D1)
wrangler dev --remote

# 指定环境
wrangler dev --env staging
local vs remote
默认 wrangler dev本地模式,用 miniflare 模拟 KV/D1。--remote 会连到真实服务,适合调试"为什么本地可以线上不行"的问题。

部署

# 默认环境
wrangler deploy

# 指定环境
wrangler deploy --env production

# 看当前已部署版本
wrangler deployments list

部署 30 秒内全球 330+ PoP 都有新版本。没错,是秒级全球发布

观察线上:实时日志

wrangler tail
# 实时流生产日志,可 --format json / --filter 'HEAD /health'

wrangler tail --env production --format json | jq .

console.log 直接出现。线上问题排查优先用 tail 而不是加 metrics。

自定义域名绑定

  1. 域名必须在 Cloudflare 托管(DNS 由 Cloudflare 接管)
  2. wrangler.toml 写 routes = ["api.example.com/*"]
  3. deploy,自动创建路由规则
  4. 访问 https://api.example.com 即命中 Worker

也可以跳过自定义域名,直接用自动给的 my-api.YOUR_SUBDOMAIN.workers.dev

常见错误与修复

Uncaught ReferenceError: process is not defined
Workers 没有 process。用 c.env / env 参数读配置,别从 process.env 读。
The script will never generate a response
fetch handler 返回了 undefined。每一条代码路径都要显式 return Response。
exceeded CPU time limit
同步代码跑太久。检查有没有在 Worker 里做重 CPU 的事(大正则、循环加密、JSON 解析上百 MB)。

本章小结