本地开发与热更新
要点
wrangler dev启动本地开发服务器,默认端口 8787- 代码保存后自动重载,不需要手动重启
- 本地可以模拟 KV、D1、R2 等 Cloudflare 绑定服务
- 日志、
--verbose、--inspect三种调试方式覆盖不同场景 --env切换多环境配置,测试不同环境的数据隔离- 本地开发、预览部署、生产部署三个阶段各有对应命令
1. wrangler dev 基础
03-topic 里用 npx wrangler dev 启动了本地服务器,这里展开讲它的行为。
在项目根目录执行:
// terminal
npx wrangler devWrangler 会在本地启动一个模拟 Cloudflare Workers 运行时的开发服务器。默认监听 http://localhost:8787,终端会输出类似信息:
// terminal
⛅️ wrangler 4.83.0
───────────────────
Your Worker is ready at http://localhost:8787访问 http://localhost:8787 就能看到 Hono 返回的内容。
自定义端口
如果 8787 被占用,或者你想用习惯的端口:
// terminal
npx wrangler dev --port 3000服务就跑在 http://localhost:3000 了。
热更新机制
wrangler dev 会监听项目文件变化。保存文件后,Wrangler 自动重新加载代码,浏览器刷新即可看到改动。不需要手动停止再重启。
这个机制基于文件系统的 watch 事件。保存动作触发文件变更通知,Wrangler 收到后重新编译并替换运行中的 Worker 实例。整个过程通常在 1 秒以内。
2. 本地绑定 KV / D1 / R2
实际项目很少只用纯计算。你的 Worker 可能需要 KV 存会话、D1 存业务数据、R2 存文件。这些服务在本地也能跑。
在 wrangler.jsonc 中配置绑定
// wrangler.jsonc
{
"name": "my-api",
"main": "src/index.ts",
"compatibility_date": "2026-04-15",
// 本地开发用的绑定
"kv_namespaces": [
{
"binding": "CACHE",
"id": "your-kv-namespace-id"
}
],
"d1_databases": [
{
"binding": "DB",
"database_name": "my-database",
"database_id": "your-database-id"
}
]
}binding 是代码里访问这个服务的变量名。id 是 Cloudflare Dashboard 上创建对应资源后拿到的标识。
Miniflare 的作用
本地开发时,你不需要真的去 Cloudflare 创建 KV 命名空间或 D1 数据库。Wrangler 内部集成了 Miniflare——一个 Cloudflare Workers 运行时的本地模拟器。
Miniflare 在本地用内存或磁盘文件模拟 KV、D1、R2 的行为。你在 wrangler.jsonc 里声明了绑定,Wrangler 启动时自动用 Miniflare 创建对应的模拟实例。代码里 c.env.CACHE.get('key') 和线上行为一致,只是数据存在本地。
3. 日志与调试
console.log 输出
最基础的调试方式。在 Hono 代码里写 console.log(),输出直接打印在 wrangler dev 的终端里:
// src/index.ts
app.get('/api/users/:id', (c) => {
const id = c.req.param('id')
console.log('收到请求,用户 ID:', id)
return c.json({ id })
})终端会显示:
// terminal
收到请求,用户 ID:42查看请求日志
wrangler dev 默认在终端打印每个请求的方法、路径和响应状态码:
// terminal
GET /api/users/42 200 OK
POST /api/users 201 Created加 --verbose 可以看到更多信息,包括启动配置、文件监听路径、绑定状态等:
// terminal
npx wrangler dev --verbose在浏览器 DevTools 中调试
如果你想用断点调试,可以用 --inspect 参数启用 Node.js 调试协议:
// terminal
npx wrangler dev --inspect终端会输出类似:
// terminal
Debugger listening on ws://127.0.0.1:9229/...打开 Chrome,访问 chrome://inspect,点击「Configure」添加 localhost:9229,然后点「inspect」就能进入 DevTools。可以在代码里设断点、单步执行、查看调用栈和变量值。
在 package.json 里加一个快捷脚本会更方便:
// package.json
{
"scripts": {
"dev": "wrangler dev",
"dev:debug": "wrangler dev --inspect"
}
}之后 pnpm dev:debug 就能启动带调试的开发服务器。
4. 本地测试策略
curl 快速测试
curl 是最快的验证方式,适合检查返回格式、状态码和 Header:
// terminal
# 基础 GET
curl http://localhost:8787/api/health
# 带路径参数
curl http://localhost:8787/api/users/42
# POST 带 JSON body
curl -X POST http://localhost:8787/api/users \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "[email protected]"}'
# 查看响应头
curl -v http://localhost:8787/api/health-v 会输出完整的请求和响应头信息,排查 Content-Type、CORS Header 等问题时很有用。
httpie 和 Insomnia
httpie 输出更友好,自带语法高亮和格式化:
// terminal
# 安装
brew install httpie
# 使用
http GET localhost:8787/api/users/42
http POST localhost:8787/api/users name=Alice [email protected]如果需要保存请求集合、测试 WebSocket 或做更复杂的测试编排,Insomnia 或 Postman 这类图形化工具更合适。
Vitest 单元测试
自动化测试简要提一下。Hono 官方推荐 Vitest,配合 @cloudflare/vitest-pool-workers 可以在测试中直接调用 Worker:
// tests/index.test.ts
import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:test'
import { describe, it, expect } from 'vitest'
import app from '../src/index'
describe('Users API', () => {
it('returns user by id', async () => {
const req = new Request('http://localhost/api/users/42')
const ctx = createExecutionContext()
const res = await app.fetch(req, env, ctx)
await waitOnExecutionContext(ctx)
expect(res.status).toBe(200)
const data = await res.json()
expect(data.id).toBe('42')
})
})cloudflare:test 提供的 env 包含了 wrangler.jsonc 里声明的所有绑定,测试环境和 wrangler dev 使用同一套 Miniflare 模拟。
5. 多环境本地开发
实际项目中,preview 和 production 环境通常对应不同的 KV 命名空间、D1 数据库或 R2 存储桶。本地开发时也需要测试不同环境的数据隔离。
Wrangler 支持通过 --env 切换配置:
// wrangler.jsonc
{
"name": "my-api",
"main": "src/index.ts",
"compatibility_date": "2026-04-15",
"kv_namespaces": [
{ "binding": "CACHE", "id": "dev-kv-id" }
],
"env": {
"preview": {
"kv_namespaces": [
{ "binding": "CACHE", "id": "preview-kv-id" }
]
},
"production": {
"kv_namespaces": [
{ "binding": "CACHE", "id": "prod-kv-id" }
]
}
}
}启动时指定环境:
// terminal
# 使用 preview 环境配置
npx wrangler dev --env preview
# 使用 production 环境配置
npx wrangler dev --env production--env preview 会让 Wrangler 合并基础配置和 [env.preview] 的配置。上面这个例子中,preview 环境的 CACHE 绑定会指向 preview-kv-id,和默认的 dev-kv-id 隔离。
注意两件事:
- 环境名必须和 wrangler.jsonc 里的
[env.xxx]对应,不存在的名字会报错 wrangler dev默认不使用任何 env,除非显式传入--env
6. 常见问题与技巧
端口被占用
最常见的问题。8787 端口被其他进程占用时,Wrangler 会直接报错退出:
// terminal
Error: Port 8787 is already in use用 lsof 查看谁占了端口:
// terminal
lsof -i :8787然后结束对应进程,或者换个端口:
// terminal
npx wrangler dev --port 8788热更新不生效
保存文件后代码没有更新。这种情况多数和编辑器的保存方式有关。
部分编辑器默认开启「安全保存」(atomic save),先写临时文件再替换原文件。Wrangler 的文件监听器可能检测不到这种替换。解决办法是关闭安全保存,或者在 Vim 里用 :w 而不是 :wq 触发保存。
如果问题持续,加 --verbose 看 Wrangler 在监听哪些路径:
// terminal
npx wrangler dev --verbose绑定数据「旧」了
KV 或 D1 的本地数据有时看起来「旧」了。Miniflare 会把数据持久化到磁盘(默认在 .wrangler/state/ 目录),重启 wrangler dev 后数据还在。
想清空本地数据重新来,删掉 .wrangler/state/ 目录就行:
// terminal
rm -rf .wrangler/stateCORS 本地调试
前端跑在 localhost:5173,Workers 跑在 localhost:8787,端口不同就是跨源。浏览器会拦截跨源请求,除非服务端显式允许。
在 Hono 里加 CORS 中间件:
// src/index.ts
import { Hono } from 'hono'
import { cors } from 'hono/cors'
const app = new Hono()
app.use('/*', cors({
origin: 'http://localhost:5173',
allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
}))本地调试时可以临时用 origin: '*' 允许所有来源,上线前记得改成具体域名。
7. 从本地到部署的流程
本地开发只是起点。从写代码到用户能用,中间还有预览和生产两个阶段。三个阶段对应三条命令:
| 阶段 | 命令 | 说明 |
|---|---|---|
| 本地开发 | wrangler dev | 本地模拟,热更新,调试用 |
| 预览部署 | wrangler versions upload | 上传到 Cloudflare,不自动激活 |
| 生产部署 | wrangler deploy | 直接推到生产环境 |
- 本地开发:
wrangler dev提供热更新,改完代码刷新就能看到效果。绑定服务由 Miniflare 模拟 - 预览部署:
wrangler versions upload把代码上传到 Cloudflare,但不会自动激活。需要在 Dashboard 手动确认激活哪个版本。适合在真实 Cloudflare 环境测试集成 - 生产部署:
wrangler deploy直接推到生产环境。绑定、日志、监控都指向真实资源
本地阶段验证逻辑,预览阶段验证集成,生产阶段验证真实表现。
延伸阅读
总结
这篇围绕 wrangler dev 展开了本地开发的方方面面:热更新、本地绑定、日志输出、浏览器调试、多环境切换、常见问题处理。
核心能力组合起来就是一个高效的开发循环:写代码 → 保存 → 自动重载 → curl 验证 → console.log 排查 → 满意后部署。
一个值得记住的点:Miniflare 在本地模拟了整个 Cloudflare Workers 运行时,所以本地行为与线上高度一致。遇到「本地能跑、线上不行」的情况,先用 wrangler tail 看线上日志,判断是运行时差异还是绑定配置问题。
下一篇讲 Hono 的路由系统,看看动态路由匹配、路由分组和中间件的组织方式。