配了三年 E2E 测试,今天才发现 Cypress 15 到 16 的迁移没有想象中那么简单
配了三年 E2E 测试,今天才发现 Cypress 15 到 16 的迁移没有想象中那么简单
每次打开 Cypress 跑 E2E 测试,以为版本升级只是改个数字——直到你发现团队里几十个 spec 文件全部报错,Cypress.env() 全局报红,cy.exec() 直接消失,CI 彻底跑不动了。
Cypress 16 在 2026 年 9 月 1 日正式发布。这个版本干掉了三个用了几年的 API,顺手把底层依赖全部升级,还给 Chrome 加了 HTTP/2 网络拦截——不是小版本,是大版本。升级窗口很短,团队需要现在就行动。
第一个:cy.exec() 没了,cy.task() 要自己管超时
这是改动最大的一块。cy.exec() 在 Cypress 16 里直接消失,取而代之的是 cy.task() + taskTimeout。
旧的写法:
// Cypress ≤15
cy.exec('npm run build', { timeout: 60000 });
新的写法:
// Cypress 16+
cy.task('exec', { cmd: 'npm run build' }, { timeout: 60000 });
但 task() 默认超时是 60 秒,如果你之前写的 timeout 比这个短,要显式覆盖。更重要的是:cy.task() 运行在 Node.js 进程里,任何崩溃都会导致测试失败,不像 exec() 那样有隔离保护。
影响范围:如果你的项目里有 cy.exec() 来跑构建命令、调用 CLI 工具或者执行系统命令,所有这些地方都要改。
第二个:Cypress.env() 变成异步了
这是最多人踩坑的地方。Cypress.env() 以前是同步的,随便在哪都能读:
// Cypress ≤15 — 同步,到处都能读
const token = Cypress.env('API_TOKEN');
cy.request('/api/data', { headers: { Authorization: token } });
Cypress 16 改成了异步,而且彻底分离了「敏感值」和「公开配置」的读取路径:
// Cypress 16 — 异步,敏感值走 cy.env([]).then()
cy.env(['API_TOKEN']).then(token => {
cy.request('/api/data', { headers: { Authorization: token } });
});
// 公开配置走 cypress.expose(),在 config 文件里声明
export default defineConfig({
expose: ['BASE_URL', 'USER_EMAIL'],
env: {
BASE_URL: 'https://staging.example.com',
USER_EMAIL: 'test@example.com',
}
});
这个改动的原因很明确:Cypress 15 及之前,所有 env 值都会灌进浏览器内存,API Token、数据库密码这些敏感信息在 DevTools 里随便看。Cypress 16 把这个后门堵上了——敏感值永远在 Node.js 进程里流转,只有显式调用才会进浏览器。
影响范围:任何直接用 Cypress.env() 读 token 或密钥的测试都要改。一个有 200 个 spec 文件的仓库,如果大量用同步 env 读取,迁移工作量不小。好在 Cypress 官方出了一个 AI-assisted upgrade prompt,Claude Code 可以帮着一键生成迁移脚本。
第三个:Node.js 版本要求直接跳到 22/24/26
Cypress 16 不再支持 Node.js 20 和 25,安装层面就过不去。最低要求变成了:
- Node.js 22.x ✅
- Node.js 24.x ✅
- Node.js 26.x ✅
还在用 Node.js 18 或者卡在 Node.js 20 LTS 的团队,升级 Cypress 之前要先升 Node。如果你的 CI 镜像是严格锁版本的,这个改动会卡住整个 pipeline。
第四个:Chrome/Edge 流量走原生网络栈,HTTP/2 默认开启
这是对生产环境最有价值的改动,也是最容易被忽略的隐性破坏点。
Cypress 16 里,Chrome、Chromium 和 Edge 的测试流量不再经过 Cypress 的代理层,而是直接走浏览器原生网络。HTTP/1.1 的六连接上限不存在了,多路复用直接可用,你的应用在测试环境里会表现得和线上完全一样。
这听起来是好事,但有几个副作用:
- 如果你的测试依赖了 Cypress 代理层的请求日志,有些用法会失效
- 某些 mock 行为在 HTTP/2 下和 HTTP/1.1 不一样,特别是并发请求的时序
- forceHttp1 这个 escape hatch 存在,但它是临时的,Cypress 17 之后会移除
第五个:component testing 的框架最低版本集体上调
如果你用 Cypress 做 React/Vue 组件测试,新版本的最低要求是:
- Angular 21+
- Next.js 15.0.4+ 或 16+
- Vite 8+
卡在 Angular 18 或者 Next.js 14 的团队,升级 Cypress 之前要先升级框架本身。这个依赖链可能比 Cypress 本身更难搞。
三步迁移路径
第一步:跑官方迁移检查
cypress install --force # 先升级 Cypress
npx cypress open # 会弹出 AI-assisted upgrade prompt
这个 prompt 会扫描你的 spec 文件,识别出所有 cy.exec() 和 Cypress.env() 调用,生成对应的修改建议。
第二步:优先处理 cy.exec()
把项目里所有 cy.exec() 替换成 cy.task(),记得在 plugins/index.js 里注册对应的 task handler:
// plugins/index.js
on('task', {
exec({ cmd }) {
return require('child_process').execSync(cmd, { encoding: 'utf-8' });
}
});
第三步:分类处理 Cypress.env()
区分两类 env 值:敏感信息(Token、密钥)走异步 cy.env([]).then() 路径;公开配置(BASE_URL、测试用户)迁移到 config 里的 expose 块。
你的 CI 现在能跑 Cypress 16 吗?
对照检查:
- CI 机器的 Node.js 版本 >= 22?
- 项目里有多少处 cy.exec()?有没有超过 20 处?
- Cypress.env() 读敏感值的场景有多少?
- component testing 用的是哪个框架版本?
如果三个问题里有两个答不上来,升级 Cypress 16 的优先级要提到这周。不要等到 Cypress 15 的安全更新停止推送之后再动手,那时候就真的被动了。
评论区
登录后可评论。