cf migrate 将 Wrangler 配置文件转换为 cloudflare.config.ts,并将 cf 添加到项目。它处理大部分转换,然后列出需要你手动完成的事项。本页覆盖完整迁移:预览、运行、解决后续事项、完成项目、验证和部署。
本页示例迁移 orders-api,这是一个带有 D1 数据库、队列、cron 触发器、路由和 Durable Object 的 Worker:
{
"name": "orders-api",
"main": "src/index.ts",
"upload_source_maps": true,
"account_id": "<ACCOUNT_ID>",
"compatibility_date": "2026-08-24",
"compatibility_flags": ["nodejs_compat"],
"vars": {
"ENVIRONMENT": "production",
},
"d1_databases": [
{
"binding": "DB",
"database_name": "orders-db",
"database_id": "<DATABASE_ID>",
},
],
"queues": {
"producers": [{ "binding": "JOBS", "queue": "orders-jobs" }],
"consumers": [{ "queue": "orders-jobs", "max_batch_size": 10 }],
},
"routes": [{ "pattern": "api.example.com/*", "zone_name": "example.com" }],
"triggers": {
"crons": ["0 * * * *"],
},
"durable_objects": {
"bindings": [{ "name": "COUNTERS", "class_name": "Counter" }],
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["Counter"] }],
}name = "orders-api"
main = "src/index.ts"
upload_source_maps = true
account_id = "<ACCOUNT_ID>"
compatibility_date = "2026-08-24"
compatibility_flags = [ "nodejs_compat" ]
[vars]
ENVIRONMENT = "production"
[[d1_databases]]
binding = "DB"
database_name = "orders-db"
database_id = "<DATABASE_ID>"
[[queues.producers]]
binding = "JOBS"
queue = "orders-jobs"
[[queues.consumers]]
queue = "orders-jobs"
max_batch_size = 10
[[routes]]
pattern = "api.example.com/*"
zone_name = "example.com"
[triggers]
crons = [ "0 * * * *" ]
[[durable_objects.bindings]]
name = "COUNTERS"
class_name = "Counter"
[[migrations]]
tag = "v1"
new_sqlite_classes = [ "Counter" ]- 安装
cf并满足其要求。直到部署时才需要登录。 - 提交或暂存每项更改,包括未跟踪的文件。当仓库中任何位置的
git status报告有更改时,cf migrate不会写入文件。.gitignore排除的文件不计入。 - 安装项目依赖。使用 Wrangler 打包器时,Worker 的软件包需要安装 Wrangler 4.136.0 或更高版本。
cf migrate用它写入wrangler.config.ts,cf dev、cf build和cf deploy会运行它。 - 不要先在项目中运行
cf dev、cf build或cf deploy。在未迁移的项目中,它们会写入自己的配置或失败。
在包含 Wrangler 配置文件的目录中运行:
cf migrate --dry-run不带路径时,cf migrate 会在当前目录中查找恰好一个 wrangler.json、wrangler.jsonc 或 wrangler.toml 文件。对于其他位置的配置文件(例如 monorepo 中的软件包),请传入其路径:
cf migrate packages/api/wrangler.jsonc --dry-runcf migrate 会在配置文件旁边写入文件。
Dry run 列出它将更改的文件和后续事项。它不会显示文件内容。对于 orders-api,它会打印:
Using the Wrangler bundler because @cloudflare/vite-plugin is not declared. Pass --bundler vite to override.
Would update 4 file(s):
├─ cloudflare.config.ts
├─ wrangler.config.ts
├─ package.json
└─ package-lock.json
Follow-up work:
├─ [required] durable_objects.bindings.0: Durable Object bindings require manual review after migration.
│ └─ https://developers.cloudflare.com/workers/runtime-apis/context/#exports
└─ [required] migrations: Wrangler Durable Object migrations are unsupported. Replace them with an exports lifecycle declaration, for example `exports: { MyDurableObject: exports.durableObject({ storage: "sqlite" }) }`.
└─ https://developers.cloudflare.com/workers/runtime-apis/context/#exports
⚠ Migration requires follow-up work.与实际运行一样,只要仍有 [required] 项,dry run 就会以状态码 1 退出。它不会检查 Git 工作区是否干净。
cf migrate 根据 Wrangler 配置文件旁边的 package.json 为迁移后的项目选择打包器:
| 打包器 | 选择时机 | 构建方式 | 构建设置所在位置 |
|---|---|---|---|
| Vite | 声明了 @cloudflare/vite-plugin |
Vite 和 Cloudflare Vite 插件 | vite.config.ts |
| Wrangler | 未声明 @cloudflare/vite-plugin |
项目中安装的 Wrangler | cf migrate 写入的 wrangler.config.ts |
不传入 --bundler 时,输出的第一行会解释该选择,如 orders-api 预览所示。要覆盖该选择,请传入 --bundler vite 或 --bundler wrangler。
cf migrate 不会安装 Vite 或创建 vite.config.ts。要将尚未使用 Vite 的项目迁移到 Vite 打包器,请传入 --bundler vite,然后安装 Vite 以及 cf 使用的 Cloudflare Vite 插件 Beta:
npm i -D vite @cloudflare/vite-plugin@betayarn add -D vite @cloudflare/vite-plugin@betapnpm add -D vite @cloudflare/vite-plugin@betabun add -d vite @cloudflare/vite-plugin@beta然后创建 vite.config.ts:
import { cloudflare } from "@cloudflare/vite-plugin";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [cloudflare()],
});如果项目已经使用 Cloudflare Vite 插件,请以相同方式安装 @cloudflare/vite-plugin@beta。该 Beta 读取 cloudflare.config.ts,没有 configPath 选项。如果 vite.config.ts 向 cloudflare() 传入了 configPath,请将其移除。
使用与 dry run 相同的参数运行 cf migrate,但不带 --dry-run:
cf migratecf migrate 接受这些参数:
| 参数 | 说明 |
|---|---|
[path] |
Wrangler 配置文件的路径。默认为当前目录中唯一的 wrangler.json、wrangler.jsonc 或 wrangler.toml。 |
--bundler |
vite 或 wrangler。省略时根据 package.json 选择。 |
--dry-run |
列出将更改的文件而不写入。 |
--force |
即使 Git 工作区不干净也运行。它不会绕过任何其他检查。 |
--no-install |
跳过将 cf 添加到项目。 |
使用 git status 和 git diff 审查更改。cf migrate 会更改这些文件:
| 文件 | 更改 |
|---|---|
cloudflare.config.ts |
在 Wrangler 配置文件旁边创建 |
wrangler.config.ts |
仅在使用 Wrangler 打包器时创建。它保存 Wrangler 构建设置。 |
package.json 和 lockfile |
更新以将 cf 添加为开发依赖 |
| Wrangler 配置文件 | 不变 |
软件包脚本、vite.config.ts、.gitignore、tsconfig.json 和源码 |
不变 |
项目需要自己的 cf 依赖,因为 cloudflare.config.ts 从 cf/config 导入。cf migrate 使用项目所用的包管理器安装它,依据 packageManager 字段或 lockfile。使用 npm 时,安装还会以两个空格缩进重写 package.json。
如果唯一的 package.json 位于父目录(例如 workspace 根目录),cf migrate 不会更改它。请改为在包含 Worker 的软件包中安装 cf。
cf migrate 从不覆盖文件。如果 cloudflare.config.ts 已存在,或你使用 Wrangler 打包器且 wrangler.config.ts 已存在,它会停止。--force 不会改变这一点。
每项后续事项有两个级别之一:
[required]:必须在项目构建之前解决。只要仍有必需项,cf migrate就会以状态码1退出。这并不表示迁移失败。[info]:无需更改的上下文。
cf migrate 还会将每个必需项作为 TODO(@cloudflare) 注释写入 cloudflare.config.ts。当仍有必需项时,它会在文件顶部添加 throw 语句。在删除该语句之前,cf dev、cf build 和 cf deploy 会失败并显示此错误:
Error: Migration incomplete. Resolve every cf migrate TODO in `cloudflare.config.ts`.对于 orders-api,cf migrate 会生成此文件:
import { bindings, defineConfig, triggers } from "cf/config";
/**
* This migration needs manual work. Resolve every TODO in this file, then remove the error below.
*/
/**
* TODO(@cloudflare): cf migrate: durable_objects.bindings.0: Durable Object bindings require manual review after migration.
* @see https://developers.cloudflare.com/workers/runtime-apis/context/#exports
*/
/**
* TODO(@cloudflare): cf migrate: migrations: Wrangler Durable Object migrations are unsupported. Replace them with an exports lifecycle declaration, for example `exports: { MyDurableObject: exports.durableObject({ storage: "sqlite" }) }`.
* @see https://developers.cloudflare.com/workers/runtime-apis/context/#exports
*/
throw new Error("Migration incomplete. Resolve every cf migrate TODO in `cloudflare.config.ts`.");
export default defineConfig({
accountId: "<ACCOUNT_ID>",
worker: {
name: "orders-api",
compatibilityDate: "2026-08-24",
compatibilityFlags: [
"nodejs_compat",
],
entrypoint: "src/index.ts",
triggers: [
triggers.fetch({
pattern: "api.example.com/*",
zone: "example.com",
}),
triggers.scheduled({
schedule: "0 * * * *",
}),
triggers.queue({
maxBatchSize: 10,
name: "orders-jobs",
}),
],
env: {
ENVIRONMENT: bindings.text("production"),
DB: bindings.d1({
name: "orders-db",
id: "<DATABASE_ID>",
}),
JOBS: bindings.queue({
name: "orders-jobs",
}),
COUNTERS: bindings.durableObject({
worker: "orders-api",
exportName: "Counter",
}),
},
/**
* TODO(@cloudflare): cf migrate: Durable Object bindings require manual review after migration.
* @see https://developers.cloudflare.com/workers/runtime-apis/context/#exports
*/
/**
* TODO(@cloudflare): cf migrate: Wrangler Durable Object migrations are unsupported. Replace them with an exports lifecycle declaration, for example `exports: { MyDurableObject: exports.durableObject({ storage: "sqlite" }) }`.
* @see https://developers.cloudflare.com/workers/runtime-apis/context/#exports
*/
},
});某些事项链接到 Wrangler 或 Workers 运行时文档。下一节说明如何为 cf 解决每项。解决所有事项后,请删除 TODO(@cloudflare) 注释、以 This migration needs manual work 开头的注释,以及 throw 语句。
带有 Durable Objects 的项目始终有必需项:每个 Durable Object 绑定一项,以及 migrations 历史一项。cf migrate 会转换每个绑定,但不会转换 migrations。
-
从
cf/config导入exports。在worker下,为当前仍存活的每个 Durable Object 类添加exports条目。匹配该类已使用的存储:用new_sqlite_classes创建的类使用"sqlite",用new_classes创建的类使用"legacy-kv"。exports: { Counter: exports.durableObject({ storage: "sqlite" }), }, -
审查每个生成的绑定。在
bindings.durableObject({ worker, exportName })中,worker是定义该类的 Worker 名称,exportName是类名。 -
删除这些事项的 TODO 注释。
不要复制已经应用的重命名或删除。对于仍需重命名、删除或转移的类,请参阅转换 Durable Object 迁移。
cf migrate 将每个 env.<NAME> 块转换为 switch (ctx.mode) 语句的一个 case。每个 case 返回一份完整配置。它遵循 Wrangler 的继承规则:顶层的绑定、vars 和 secrets 不会复制到环境中。没有自己的 name 的环境会得到 <NAME>-<ENVIRONMENT>。生成的配置具有此形状:
export default defineConfig((ctx) => {
switch (ctx.mode) {
case "staging": {
return {
worker: {
name: "orders-api-staging",
// ...
},
};
}
default: {
return {
worker: {
name: "orders-api",
// ...
},
};
}
}
});将 --env <NAME> 替换为 --mode <NAME>:
cf build --mode staging
cf deploy --mode staging适用于顶层配置的必需项会再次出现在继承它的每个环境中。
不带 --mode 时,Wrangler 打包器使用 default 分支。Vite 打包器对 cf dev 使用 development 模式,对 cf build 和 cf deploy 使用 production。使用 Vite 打包器时,名为 production 或 development 的环境会在不带 --mode 时被选中,因此 cf migrate 会将其标记为必需。请将该 case 重命名,例如改为 "prod",并用 --mode 传入新名称。
所有命令的模式默认值请参阅将环境转换为模式。
Wrangler 构建字段(例如 build、minify、alias 和 assets.directory)不属于 cloudflare.config.ts。
使用 Wrangler 打包器时,cf migrate 会将它们以 camelCase 键移到 wrangler.config.ts,无需后续事项。例如:
import { defineWranglerConfig } from "wrangler/experimental-config";
export default defineWranglerConfig({
alias: {
lodash: "lodash-es",
},
minify: true,
uploadSourceMaps: true,
build: {
command: "npm run build:css",
},
dev: {
port: 8788,
},
types: {
generate: false,
},
assetsDirectory: "./public",
});wrangler.config.ts 是实验性的,在 Beta 期间可能变化。
使用 Vite 打包器时,cf migrate 会在必需项中列出这些字段,并且不会移动它们。请将每项设置移到 vite.config.ts 中的 Vite 等效项,例如将 alias 移到 resolve.alias。每个字段请参阅构建设置。
自定义 build 命令不会带到 Vite 打包器。cf build 直接运行 Vite,因此请先自行运行该命令,例如 npm run build:css && cf build。
使用 Vite bundler 时,cf migrate 不会移动 upload_source_maps,而会将其报告为后续处理项。cf deploy 会上传构建输出中的每个 source map;从 1.64.0 版本开始,Cloudflare Vite plugin 默认会为 Worker 的 Vite 环境生成 source map。你无需替换 upload_source_maps: true。
要停止上传 source map,请在 Worker 的 Vite 环境中将 build.sourcemap 设置为 false。默认情况下,Cloudflare Vite plugin beta 将 Worker 环境命名为 ssr:
import { cloudflare } from "@cloudflare/vite-plugin";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [cloudflare()],
environments: {
ssr: {
build: {
sourcemap: false,
},
},
},
});在较早版本的 Cloudflare Vite plugin 中,请将 build.sourcemap 设置为 true 以生成 source map。
cf migrate 报告源映射的方式在 Beta 期间可能变化。
cf migrate 不会转换 D1 绑定的 migrations_dir、migrations_pattern 或 migrations_table 字段。请改为将它们传给 cf d1 migrations apply:
| Wrangler 字段 | cf d1 migrations apply 选项 |
|---|---|
migrations_dir |
--dir,默认为 ./migrations |
migrations_pattern |
--pattern |
migrations_table |
--table,默认为 d1_migrations |
例如:
cf d1 migrations apply <DATABASE_ID> --dir db/migrationscf d1 migrations apply 接受数据库 ID。与 Wrangler 不同,除非添加 --local,否则它会将迁移应用到远程数据库。
按如下方式解决其余事项,然后删除每个 TODO 注释:
| 事项 | 做法 |
|---|---|
预览资源:preview_id、preview_bucket_name、preview_database_id |
cloudflare.config.ts 没有预览资源字段。在 cf dev 期间,除非在绑定上设置 dev: { remote: true },否则绑定使用本地资源。 |
使用 zone_id 的路由 |
cf migrate 将 zone ID 复制到 triggers.fetch() 的 zone 选项,该选项接受 zone 名称或 zone ID。请确认该值。 |
| 指向旧版 service environment 的 service binding | cf migrate 将目标重写为 <SERVICE>-<ENVIRONMENT>。请确认这就是要绑定的 Worker。 |
Workers Sites(site) |
不支持。将站点迁移到 Workers Static Assets。 |
previews |
转换为 ctx.isPreview 上的分支。请审查该分支。更多信息请参阅部署预览。 |
缺失的 name 或 compatibility_date |
替换为占位符 "TODO" 和 "YYYY-MM-DD"。请设置真实值。 |
不支持或未知的字段,例如 keep_vars |
移除它们,或在配置参考中查找等效项。 |
安装 cf |
出现在使用 --no-install、安装失败,或配置文件旁边没有 package.json 时。请在 Worker 的软件包中安装 cf。 |
要将 cf 安装为开发依赖,请运行:
npm i -D cfyarn add -D cfpnpm add -D cfbun add -d cfcf migrate 不会转换 Workflow 绑定或 Containers 配置。它将两者都报告为必需项。请手动将它们添加到 cloudflare.config.ts:
- 对于 Workflow,在定义它的 Worker 中用
exports.workflow({ name })声明类。用bindings.workflow({ name, worker, exportName })绑定到它。请参阅声明导出。 - 对于 Container,用
defineContainer()定义它,将其添加到顶层containers数组,并从exports.durableObject({ storage: "sqlite", container })条目引用它。请参阅附加 Container。
然后删除每项的 TODO 注释。
cf migrate 从不读取 secret 文件。它将找到的任何 .dev.vars 或 .env 文件列为 [info] 项。cf dev 仍会为本地开发加载 .dev.vars。
secrets.required 中的条目变为 bindings.secret() 值。以相同方式声明 Worker 读取的任何其他 secret:
env: {
API_TOKEN: bindings.secret(),
},要随新版本上传 secrets,请向 cf deploy 或 cf workers versions create 传入 --secrets-file <PATH>。文件可以是 JSON 或 .env 格式。
cf migrate 将项目的其余部分留给你:
-
替换
package.json脚本中的 Wrangler 命令。Wrangler 命令读取 Wrangler 配置文件,并忽略cloudflare.config.ts。package.jsonjson { "scripts": { "dev": "cf dev", "build": "cf build", "deploy": "cf deploy" } }cf build直接运行 Vite 或 Wrangler,而不是你的build脚本。要运行额外步骤,请自行串联,例如tsc -b && cf build。 -
将
.cloudflare/添加到.gitignore。该目录保存 Build Output、生成的类型以及cf生成的其他文件。 -
在
package.json中设置"type": "module"。否则,每次cf加载cloudflare.config.ts时,Node.js 都会打印MODULE_TYPELESS_PACKAGE_JSON警告。 -
生成类型:
- 使用 Vite 打包器时,
cf dev和cf build写入.cloudflare/types/index.d.ts。 - 使用 Wrangler 打包器时,
cf migrate在wrangler.config.ts中设置types: { generate: false }。将其改为true,或运行cf workers types。
然后将生成的类型添加到
tsconfig.json:tsconfig.jsonjson { "include": ["src", "cloudflare.config.ts", ".cloudflare/types"] } - 使用 Vite 打包器时,
-
(可选)将字符串
entrypoint替换为使用cf-worker属性的导入:cloudflare.config.tsts import * as entrypoint from "./src/index.ts" with { type: "cf-worker" };在
worker下,将entrypoint: "src/index.ts"替换为entrypoint。使用字符串路径时,仍会推断Env绑定类型,但不会获得 Worker 模块导出的类型。要对.ts导入路径进行类型检查,请在tsconfig.json中设置allowImportingTsExtensions。
orders-api 的完成后版本请参阅完整示例。
使用 cf dev 在本地启动项目,并检查它能响应。然后停止开发服务器,构建项目,并运行 dry-run 部署:
cf build
cf deploy --dry-run这些命令都不需要你登录。cf deploy --dry-run 会构建项目,打印它将部署的绑定,并且不上传任何内容。
如果项目有环境,也请验证每个模式:
cf build --mode staging
cf deploy --dry-run --mode staging登录,然后部署:
cf auth login
cf deploycf deploy 会构建项目、上传新的 Worker Version,并部署它。部署选项请参阅开发、构建和部署。要从 CI 部署,请参阅在 CI 中使用 cf。
一旦存在 cloudflare.config.ts,cf 就会忽略 Wrangler 配置文件。在你用 cf 部署,并且脚本和 CI 都使用 cf 之后,删除 Wrangler 文件。
Wrangler 不会读取 cloudflare.config.ts。如果你仍在项目中运行 Wrangler 命令(例如 wrangler tail),请在不再需要它们之前保留 Wrangler 配置文件。
No Wrangler config found in <DIRECTORY>. Pass its path to cf migrate.在包含 Wrangler 配置文件的目录中运行 cf migrate,或传入文件路径。如果目录包含多个 Wrangler 配置文件,cf migrate 会报告 Multiple Wrangler configs found in <DIRECTORY>。请传入确切路径。
Git worktree is not clean. Commit or stash your changes before running a codemod, or rerun with `--force` to bypass this safety check.提交或暂存每项更改(包括未跟踪的文件),然后再次运行迁移。
Cannot migrate because <PATH>/cloudflare.config.ts already exists. Inspect and finish the existing migration; it will not be overwritten. Automated agents should read its TODOs and ask the user about unresolved choices.如果先前的 cf migrate 运行创建了该文件,请完成该迁移。如果是 cf dev、cf build 或 cf deploy 创建了它,请按仅在迁移后再运行项目命令所述撤销其更改,然后运行 cf migrate。
使用 Wrangler 打包器时,即使是 dry run,cf migrate 也需要本地 Wrangler 安装。没有时,它会报告:
Generating wrangler.config.ts requires wrangler 4.100.0 or newer because earlier versions do not export wrangler/experimental-config. No local Wrangler installation was found. Update Wrangler and retry the migration.迁移之后,cf dev、cf build 和 cf deploy 需要 Wrangler 4.136.0 或更高版本。使用较旧版本时,其错误包含:
cf requires [email protected] or newer for cf dev, cf build, cf deploy, and cf previews deploy.安装项目依赖或更新 Wrangler,然后再次运行命令。
Error: Migration incomplete. Resolve every cf migrate TODO in `cloudflare.config.ts`.解决后续事项,然后删除 cloudflare.config.ts 顶部的 throw 语句。
Error: cloudflare.config.ts is required when --experimental-new-config is enabled.cf dev、cf build 或 cf deploy 在尚未迁移的 Wrangler 项目中运行。请运行 cf migrate。
wrangler is declared in <PATH>/package.json but is not installed.安装项目依赖。cf 只在 Worker 软件包自己的 node_modules 目录中查找 Wrangler。在 monorepo 中,提升到 workspace 根目录的副本不算。
如果 package.json 两个软件包都未声明,例如因为你使用全局 Wrangler 安装,错误会以 No Cloudflare dev-server is installed in this project 开头。请将 Wrangler 添加为开发依赖,或按选择打包器所述安装 Vite 和 Cloudflare Vite 插件。
全局 cf 会运行项目中安装的 cf 副本。如果项目固定了没有 cf migrate 的较旧 cf,请更新项目的 cf 依赖,或用 npx cf@latest migrate 运行一次最新版本。