跳转到内容
本站为社区维护的非官方中文翻译,与 Cloudflare, Inc. 无关联。本站不提供账户登录,请勿在任何非官方站点输入您的 Cloudflare 账户信息。官方文档:developers.cloudflare.com

迁移 Wrangler 项目

最后更新 查看 MarkdownAgent 设置

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-run

cf 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@beta

然后创建 vite.config.ts:

vite.config.tsts
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 migrate

cf 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 会生成此文件:

cloudflare.config.tsts
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 Objects 的项目始终有必需项:每个 Durable Object 绑定一项,以及 migrations 历史一项。cf migrate 会转换每个绑定,但不会转换 migrations。

  1. 从 cf/config 导入 exports。在 worker 下,为当前仍存活的每个 Durable Object 类添加 exports 条目。匹配该类已使用的存储:用 new_sqlite_classes 创建的类使用 "sqlite",用 new_classes 创建的类使用 "legacy-kv"。

    exports: {
        Counter: exports.durableObject({ storage: "sqlite" }),
    },
  2. 审查每个生成的绑定。在 bindings.durableObject({ worker, exportName }) 中,worker 是定义该类的 Worker 名称,exportName 是类名。

  3. 删除这些事项的 TODO 注释。

不要复制已经应用的重命名或删除。对于仍需重命名、删除或转移的类,请参阅转换 Durable Object 迁移。

环境

cf migrate 将每个 env.<NAME> 块转换为 switch (ctx.mode) 语句的一个 case。每个 case 返回一份完整配置。它遵循 Wrangler 的继承规则:顶层的绑定、vars 和 secrets 不会复制到环境中。没有自己的 name 的环境会得到 <NAME>-<ENVIRONMENT>。生成的配置具有此形状:

cloudflare.config.tsts
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,无需后续事项。例如:

wrangler.config.tsts
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:

vite.config.tsts
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 期间可能变化。

D1 迁移

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/migrations

cf 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 cf

Workflows 和 Containers

cf 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 注释。

Secret

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 将项目的其余部分留给你:

  1. 替换 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。

  2. 将 .cloudflare/ 添加到 .gitignore。该目录保存 Build Output、生成的类型以及 cf 生成的其他文件。

  3. 在 package.json 中设置 "type": "module"。否则,每次 cf 加载 cloudflare.config.ts 时,Node.js 都会打印 MODULE_TYPELESS_PACKAGE_JSON 警告。

  4. 生成类型:

    • 使用 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"]
    }
  5. (可选)将字符串 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 deploy

cf deploy 会构建项目、上传新的 Worker Version,并部署它。部署选项请参阅开发、构建和部署。要从 CI 部署,请参阅在 CI 中使用 cf。

移除 Wrangler 配置

一旦存在 cloudflare.config.ts,cf 就会忽略 Wrangler 配置文件。在你用 cf 部署,并且脚本和 CI 都使用 cf 之后,删除 Wrangler 文件。

Wrangler 不会读取 cloudflare.config.ts。如果你仍在项目中运行 Wrangler 命令(例如 wrangler tail),请在不再需要它们之前保留 Wrangler 配置文件。

故障排除

未找到 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 工作区不干净

Git worktree is not clean. Commit or stash your changes before running a codemod, or rerun with `--force` to bypass this safety check.

提交或暂存每项更改(包括未跟踪的文件),然后再次运行迁移。

cloudflare.config.ts 已存在

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 缺失或过旧

使用 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 语句。

需要 cloudflare.config.ts

Error: cloudflare.config.ts is required when --experimental-new-config is enabled.

cf dev、cf build 或 cf deploy 在尚未迁移的 Wrangler 项目中运行。请运行 cf migrate。

未安装 Wrangler

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 插件。

未知命令:migrate

全局 cf 会运行项目中安装的 cf 副本。如果项目固定了没有 cf migrate 的较旧 cf,请更新项目的 cf 依赖,或用 npx cf@latest migrate 运行一次最新版本。

这篇文档对您有帮助吗?