Guide

如何将 Cloudflare Sandbox 应用迁移到 @next SDK 而不影响生产环境?

AI

AI Agent Skills

4 min

问题:你有一个正常运行的 Cloudflare Sandbox 应用,但底层正在发生变化

你在 Cloudflare 的 Sandbox 平台上构建了一个应用。它运行正常,团队每天都在使用。然后你听说稳定的 @cloudflare/sandbox SDK 即将迎来重大版本变更——Sandbox SDK 1.0——而预览版已经以 @cloudflare/sandbox@next 的形式发布。

你的第一反应可能是等到它变成稳定版再说。但这里有个问题:这次迁移不是简单的版本升级。新 SDK 改变了核心 API,移除了会话和传输层等概念,并且改变了进程执行和观察的方式。如果你等到最后一刻,就只能在压力下匆忙迁移。

真正的痛点不是迁移本身——而是不确定性。到底什么变了?你现有的哪些模式会中断?如何在切换过程中避免生产事故?如何在不花几周时间阅读文档的情况下验证一切是否正常工作?

这就是拥有一个结构化、有针对性的迁移工作流的价值所在。不是通用指南,而是一个了解具体替换模式、不可违反的硬性规则以及精确步骤顺序的技能。

为什么这次迁移不仅仅是版本升级

Cloudflare Sandbox SDK 1.0 预览版(@next)不向后兼容。这是一次重新设计。实际影响如下:

  • 会话被移除。 稳定版 SDK 使用会话来管理状态、环境和终端。@next SDK 完全移除了会话,改为在每次进程启动时配置 cwdenv
  • 传输层被移除。 稳定版 SDK 有 SANDBOX_TRANSPORTsetTransport 及相关配置。@next SDK 仅使用 RPC——没有传输抽象层。
  • 进程执行形式改变。 稳定版中 await sandbox.exec("npm test") 返回缓冲结果。在 @next 中,它返回一个进程句柄,你必须显式调用 .output() 来获取结果。
  • 终端工作方式不同。 稳定版的 sandbox.terminal(request) 模式被 createTerminal + terminal.connect(request) 替代。
  • Git 操作需要手动处理。 稳定版 SDK 有 gitCheckout 辅助方法。@next SDK 期望你通过 exec 使用 argv 调用 git
  • 终止信号仅支持数字。 不再支持字符串形式的信号名称。

这些不是边缘情况——它们是影响几乎所有 Sandbox 应用的核心 API 变更。如果你的代码库使用了这些模式中的任何一种,简单的 npm install @cloudflare/sandbox@next 会立即导致应用中断。

一个好的迁移方案应该做什么

一个有用的迁移工具或技能应该:

  1. 审计你的代码库,找出所有需要变更的模式,而不仅仅是显而易见的那些。
  2. 提供清晰的替换映射,让你确切知道每个稳定版 API 在 @next 中变成什么。
  3. 强制执行硬性规则,违反这些规则会导致生产故障(比如混用 @next Worker 和稳定版容器镜像)。
  4. 引导切换顺序,避免意外部署不兼容的 Worker 和镜像组合。
  5. 包含验证步骤,在确认迁移完成之前验证其是否成功。
  6. 知道何时停下来请求人工输入——特别是在生产切换时间和自部署桥接方面。

介绍 sandbox-migrate-to-next 技能

sandbox-migrate-to-next 技能是一个专门为这次迁移设计的结构化工作流。它不是通用的 Cloudflare 工具——它专注于一个任务:将现有应用从稳定版 @cloudflare/sandbox 移植到 @cloudflare/sandbox@next

以下是它能做和不能做的事情:

适用于:

  • 目前使用稳定版 SDK 的现有 Cloudflare Sandbox 应用
  • 为即将到来的 1.0 稳定版做准备的团队
  • 需要保留现有功能的迁移

不适用于:

  • 新项目(应使用 sandbox-next 技能)
  • 在稳定版 SDK 上的日常开发(应使用 sandbox-stable 技能)
  • 不迁移到 @next 的情况下清理已弃用 API(应使用 2026 弃用指南)

迁移工作流如何运作

该技能遵循五步流程,并在需要时设置检查点停下来请求你的输入。

第一步:审查硬性规则和替换映射

在修改任何代码之前,技能会确立不可协商的规则:

  • Worker 包和容器镜像必须在同一个 @next 版本线上。混用版本会导致应用中断。
  • 生产切换需要使用 --containers-rollout=immediate。渐进式部署会创建不兼容的混合窗口,稳定版和 @next 的控制协议会冲突。
  • 切换后,await sandbox.exec(...) 表示进程已启动,而不是已完成。这是一个根本性的行为变化。
  • 进程句柄没有 stdin。你不能向运行中的进程管道传输交互式输入。
  • 没有通用的错误重试循环。不同的错误(不可用、中断的 RPC、过期句柄、本地等待超时)需要不同的处理方式。

技能还提供完整的替换映射:

稳定版模式 @next 等价物
SANDBOX_TRANSPORT / transport / setTransport 完全移除——仅 RPC
await sandbox.exec("cmd") → 缓冲结果 await sandbox.exec(argv) → 句柄,然后 .output()
execStream / startProcess 同一句柄:.logs.waitFor*.kill
默认/命名会话 移除——每次启动使用 cwd/env
sandbox.terminal(request) createTerminal + terminal.connect(request)
gitCheckout 通过 exec 使用 argv 调用 git
字符串终止信号 仅支持数字

第二步:审计代码库

技能运行针对性搜索,找出每个需要变更的模式:

rg 'SANDBOX_TRANSPORT|transport:|setTransport|enableDefaultSession|createSession|getSession|deleteSession|execStream\(|startProcess\(|killProcess\(|sandbox\.terminal\(|sessionId|gitCheckout\(|SandboxTransport|ExecutionSession'

它还会查找更隐蔽的模式:字符串形式的 exec( 调用、cd 后跟后续 exec 调用(状态不会持久化),以及 Sandbox 上的裸 createCodeContext / runCode 使用。

第三步:与用户确认

这是技能停下来提问的地方。它需要你的输入:

  • 生产切换时间。 你是否接受使用 --containers-rollout=immediate?部署过程中活跃的进程、终端和流会停止。
  • 自部署桥接。 如果你有自部署桥接,它保持在稳定版上。桥接目前还不是预览版的一部分。
  • Python 解释器。 如果你的应用使用 Python,你需要 -python 镜像变体(cloudflare/sandbox:next-python)。
  • 不明确的调用点。 任何无法清晰映射到替换表的代码都需要人工判断。

第四步:升级包、镜像和代码

技能按顺序应用变更:

包和镜像:

npm install @cloudflare/sandbox@next
FROM cloudflare/sandbox:next

按区域的代码变更:

对于命令,形式从单个字符串变为 argv 数组:

// 之前(稳定版)
const result = await sandbox.exec("npm test");

// 之后(@next)
const process = await sandbox.exec(["/bin/bash", "-lc", "npm test"]);
const result = await process.output({ encoding: "utf8" });

对于长时间运行的进程:

const server = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
  cwd: "/workspace/app",
});
await server.waitForPort(3000, { timeout: 60_000 });
await server.kill(); // 数字;默认 15

对于终端:

const terminal = await sandbox.createTerminal({ command: ["bash"], cwd: "/workspace" });
const t = await sandbox.getTerminal(terminal.id);
if (!t) return new Response("terminal gone", { status: 410 });
return t.connect(request, { cursor, cols, rows });

对于解释器:

import { Sandbox as BaseSandbox } from "@cloudflare/sandbox";
import { withInterpreter } from "@cloudflare/sandbox/interpreter";

export class Sandbox extends BaseSandbox<Env> {
  interpreter = withInterpreter(this);
}

对于 git 操作:

const clone = await sandbox.exec(
  ["git", "clone", "--depth", "1", "--", repoUrl, "/workspace/repo"],
  { cwd: "/workspace" },
);
const result = await clone.output({ encoding: "utf8" });

技能还会告诉你删除所有传输设置、移除会话 API,并使用单独的 sandbox ID 隔离用户。

第五步:验证

技能运行验证清单:

  1. Lockfile 和 Dockerfile 在同一个 @next 版本线上
  2. 针对 @next 类型的类型检查通过
  3. 冒烟测试:argv exec + output({ encoding: "utf8" }) 正常工作
  4. 冒烟测试:长时间运行的进程、终端和解释器(如果使用)
  5. 错误处理区分不可用、中断的 RPC、过期和本地等待错误
  6. sandbox 环境中没有活跃的密钥
  7. Grep 确认所有已移除的 API 已被清除
  8. 生产部署使用了 --containers-rollout=immediate

何时使用此技能(何时不使用)

在以下情况使用:

  • 你有一个使用稳定版 SDK 的现有 Cloudflare Sandbox 应用
  • 你想为 1.0 稳定版做准备
  • 你需要一个带安全检查的结构化迁移路径

在以下情况不要使用:

  • 你正在开始一个新项目(应使用 sandbox-next
  • 你在稳定版 SDK 上进行日常开发(应使用 sandbox-stable
  • 你想在不迁移到 @next 的情况下清理已弃用的 API

使用此技能前需要检查什么

在运行此迁移之前,请检查:

  • 仓库信号。 该技能来自 Cloudflare 官方的 skills 仓库(2600+ 星,Apache-2.0 许可证)。由平台团队维护。
  • 安全级别。 评级为中等。迁移涉及包更改、Dockerfile 修改和生产部署命令。在应用之前审查变更。
  • 文档深度。 技能为每个区域引用特定的 Cloudflare 文档页面(进程、终端、解释器、错误、生命周期)。它在步骤需要详细信息时获取这些文档,而不是依赖记忆。
  • 你的代码库复杂性。 如果你有自部署桥接、自定义传输配置或大量会话使用,预计在澄清步骤中会有更多手动决策。
  • 生产影响。 切换是即时的,会中断进行中的工作。请计划一个维护窗口。

需要注意的危险信号

技能明确指出会导致问题的模式:

  • 混用 @next Worker 和稳定版镜像(或反之)
  • 对此次切换使用渐进式容器部署
  • await exec 视为命令完成(它只是进程启动)
  • 假设 cd 或环境变量导出在 exec 调用之间持久化
  • 对每种错误类型使用同一个重试包装器
  • 发明 API,如核心上的 gitCheckout、进程 stdin 或未记录的辅助方法
  • 部署后保留切换前的进程或终端 ID
  • 未经用户同意强制进行生产切换

总结

从 Cloudflare Sandbox 稳定版迁移到 @next 是一项重要但可管理的任务。sandbox-migrate-to-next 技能为你提供了一个结构化的工作流,涵盖审计、代码变更、切换和验证。它知道何时停下来请求你的输入,并强制执行防止生产故障的硬性规则。

目标不是让迁移变得不可见——而是让它变得可预测。你会确切知道什么变了、为什么变了,以及如何验证它是否正常工作。

延伸阅读