Cypress 16 发布:引入 HTTP/2 支持,加速端到端测试

端到端测试套件跑得慢,往往不是一个原因造成的。时间会在排队请求、人为延迟、布局抖动和因测试不稳定导致的 CI 全量重跑中悄悄流失。Cypress 16 一次性解决了所有这些问题,而且大部分改进无需你改动任何一行测试代码:
- 支持 HTTP/2,在 Chromium 系浏览器(Electron 除外)中默认开启,请求密集的页面可以并行加载,不再排队
- 全速输入,按键默认延迟降为零
- 更快的可见性算法,对大型、深层嵌套应用的提速尤其明显
- Cookie 和 storage 命令支持重试,消除常见的测试不稳定问题及其引发的重跑
- 默认开启内存管理,长时间运行不再逐渐劣化或中途崩溃
本次发布还升级了 Cypress 的底层依赖,包括 Node.js 24、Electron 41 和 Chromium 146,并完成了 Cypress 15 开始的安全工作:移除 Cypress.env(),确保敏感信息不会进入浏览器。
在我们的 测试性能指南 中,“升级到最新版 Cypress”位列优先级清单的第一项,排在任何配置调整之前。Cypress 16 就是最好的理由。
HTTP/2 支持
一直以来,Cypress 都扮演着浏览器与服务器之间的中间人,代理所有请求,让 cy.intercept() 之类的命令能够观察和修改网络流量。这套代理诞生时,HTTP/1.1 还是主流标准。但 Web 早已向前发展,如今绝大多数生产流量都走 HTTP/2。在此之前,被测应用所用的协议比真实用户访问时的还要旧。
从 Cypress 16 开始,只要服务器支持,Chromium 系浏览器中的请求就会使用 HTTP/2,你的测试代码无需任何改动。
请求密集型页面加载更快。HTTP/2 通过多路复用技术,在单一连接上并发处理多个请求,不再受限于少量并行连接槽位的排队等待。在加载 1,000 张图片的基准测试中,HTTP/2 页面的完成时间为 1,362ms,而 HTTP/1.1 下为 3,896ms。如果你的页面发起大量小型请求,尤其是通过 Vite 开发服务器时,你会在 open 模式和 CI 环境中明显感受到性能提升。
流式功能变得可测。在 HTTP/1.1 下,浏览器限制每个域名的 Server-Sent Events 连接数最多为 6 个。这一限制使得上传进度指示器、实时通知和活动动态流等场景几乎无法测试。而 HTTP/2 中,并发流数量通过与服务器协商确定,默认值为 100。如果你之前因性能瓶颈放弃测试流式工作流,现在值得重新审视。
该变更目前仅适用于基于 Chromium 的浏览器。在此版本中,Firefox 和 WebKit 仍继续使用 HTTP/1.1。
这是 Cypress 的一项重大改进,也是一次显著变更。如果你遇到问题,可以通过在配置中传入 forceHttp1: true 来禁用新行为,以便协助调试。若发现仅在新默认行为下出现的 Bug,请在 cypress 仓库中 提交 Issue。
更快的可见性检查
Cypress 16 默认采用了更现代的要素可见性算法。它会首先调用浏览器内置的可见性检查,再通过自适应点采样方法确认覆盖率,从而避免大部分布局抖动(layout thrashing)。该功能此前作为实验特性发布,现在所有用户默认可用,无需手动开启。
每当 Cypress 断言某个元素可见时,都会运行一次可见性算法。旧版算法会逐级遍历祖先节点并读取各级的 CSS 属性,这会反复触发浏览器的布局重算。在具有深层嵌套组件结构的大型页面上,且测试套件包含大量可见性断言时,这一开销会在每次运行中悄悄累积。现代算法旨在加速这些检查。
如果你需要时间进行迁移,可以在全局、套件或测试级别的 Cypress 配置中设置 visibilityStrategy: 'legacy',以恢复旧行为。
全速打字
Cypress 16 将 cy.type() 的默认按键延迟设为 0ms,表单填写速度可完全匹配应用的处理能力。此前该指令默认设置 10ms 延迟以模拟人工打字,但在包含数百个表单测试的用例集中,这种额外运行时间带来的价值有限。此项默认值变更将显著缩短整体测试时长。若应用确实依赖按键间时序(如激进防抖输入或每次按键均触发重新渲染的组件),可通过全局或单指令配置恢复原有延迟值。
长时间运行不再导致渲染进程崩溃
在长时间运行过程中,浏览器会跨测试用例累积内存。随着内存压力增加,浏览器性能下降,极端情况下甚至会在测试套件完成前崩溃。自 Cypress 12.4.0 起,建议在 Chromium 浏览器中设置 experimentalMemoryManagement 标志,以便在测试间隙清理内存。尽管我们多年推荐此配置并在内部测试中采用,但由于其实验性标志身份,大多数团队从未发现它。
Cypress 16 中该功能已稳定,更名为 manageBrowserMemory 并默认启用。
启用 manageBrowserMemory 后,Cypress 将在 Chromium 系浏览器中监控运行期间的渲染器内存,并在浏览器内存耗尽前触发垃圾回收,这将决定长时间运行的规范用例能否正常结束,还是遭遇 "检测到 Chrome Renderer 进程刚刚崩溃" 失败。
它并非通用提速方案:清理内存本身耗时,对于从未接近内存上限的轻量级用例,此举反而增加开销。该配置项保留为单个可关闭选项。长时间运行的规范用例和内存受限的 CI 容器受益最大,且无需再进行配置。
减少不稳定测试,降低重跑次数
并非所有时间浪费都表现为测试缓慢。需要每次运行的重试测试在每次运行中均产生成本,而不稳定导致失败的测试则会迫使开发者投入调查并完整重触发 CI。
Cookie 和存储的读取正是测试不稳定的常见来源。Cookie 往往是在重定向或一次服务器往返之后异步写入的,读取时如果差了几毫秒就会找不到,导致测试失败。在 Cypress 16 中,cy.getCookie()、cy.getCookies()、cy.getAllCookies()、cy.getAllLocalStorage() 和 cy.getAllSessionStorage() 都变成了查询命令,链式断言会重新读取底层状态并不断重试,直到断言通过:
cy.getCookie('session_id').should('exist')这条断言现在会像 cy.get() 等待元素一样等待 cookie 出现。少了一个竞态条件,也就少了一个让本来全绿的测试套件莫名变红的理由。
更快的基础设施
这个版本的一部分性能提升其实并不是新功能。Cypress 16 迁移到了更新的运行时和浏览器基础:底层升级到 Node.js 24,内置 Chromium 146,组件测试工具链也更新到各大主版本,包括 Vite 8 以及 Angular 21 和 22。这些升级各自带来的性能优化,你的测试都能直接受益。
我们还删掉了一些不必要的代码。其中 experimentalSourceRewriting 这个实验特性对启用它的团队来说,会让单次 cy.visit() 慢上五到十倍,如今它已被移除,而它原本想支持的能力并未丢失。几个早已废弃的 API 也一并清理了。
机密信息不再进入浏览器
Cypress.env() 已被移除。它会把所有配置的环境变量一次性注入浏览器,这意味着环境里的任何一个机密,都可能被应用代码、第三方脚本,乃至测试进入的任何跨域上下文读取到。
Cypress 16 把它拆分成两个保障不同的 API:
cy.env()异步读取敏感值并将其保留在 Node 进程中,只有你请求的键才会进入测试环境。Cypress.expose()用于发布非敏感值(如 feature flag 或公开的 API base URL),支持同步访问。
每次测试或每个测试套件中的配置覆盖不再接受 env 键,用于控制弃用的 allowCypressEnv 选项也已移除。
基于相同的目标,cypress info 命令不再打印 HTTP_PROXY、HTTPS_PROXY、NO_PROXY 或任何 CYPRESS_* 环境变量。该命令常被直接粘贴到公开的 bug 报告中,现在它仅报告文件路径、版本和系统信息。
其他破坏性变更
Cypress 16 还包含了一些其他破坏性变更,每一项在当前的 Cypress 中都有直接的替代方案。
- Electron 浏览器已被弃用。Electron 在 Cypress 16 中仍可正常工作,请参阅我们关于Electron 浏览器弃用的博客文章以获取迁移的完整详情。
- 移除了 cy.exec() 和 execTimeout。请改用 cy.task()。
- 移除了 cy.end()。你可以直接删除 .end() 调用。
- viewportWidth、viewportHeight 和 blockHosts 无法再通过 Cypress.config() 在测试执行期间设置。请改为在 describe、context 或 it 块的测试配置中设置它们。
- 移除对 CoffeeScript 的支持。
- Component Testing 不再支持 Angular 18、19 和 20
- Component Testing 不再支持 Vite 5、6 和 7
- Component Testing 不再支持 Next.js 14
如何升级到 Cypress 16
Cypress 16 迁移指南涵盖了所有变更并提供具体的操作步骤,变更日志则列出了完整清单。
此外,Cypress 16 迁移指南中包含一个现成的提示词,可粘贴到任何 AI 编程助手(如 Claude Code、Cursor、Copilot)中,它将协助你完成升级:检查你的 Node 版本和框架要求、更新依赖项,并找出需要修改的代码。审查其执行结果并提交。
还没有升级到最新的 Cypress 15?
还没准备好升级?你仍然可以获取更快的收益:先升级到 15 版本。我们在 15 系列的整个周期中持续发布性能修复,以我们能达到的最快速度通过次要版本免费推送给你。
跨越多个大版本升级,过去意味着需要阅读大量文档,现在则不然。从 10 版本开始的每个大版本都在迁移指南中提供了现成的提示词。打开你要迁移到的版本对应的章节,将提示词复制到你使用的任何 AI 编程助手中,它将协助你完成升级:检查你的 Node 版本和框架要求、更新依赖项,并找出需要修改的代码。逐个大版本审查其执行结果,持续进行直到你到达最新版本。
如果你一直停留在旧版本,以下是你错过的一些内容:
功能
- 让你的 AI 代理在本地运行、监视并修复 Cypress 测试。 (15.21.0)。cypress tap 是 Cypress CLI 的一个扩展,允许你或代理与 open-mode Cypress 会话交互,并从终端读取其上下文。它已免费包含在 Cypress 应用中。通过它,代理可以运行 spec 并轮询其状态,然后读取失败测试的 Command Log 和错误信息,显示方式与 Cypress 应用一致。它还可以检查被测应用在命令执行时刻的 DOM。
- 把自然语言步骤转化为可自愈的 Cypress 命令(15.13.0)。
cy.prompt允许你用自然语言构建测试,并在运行时自动修复失效的选择器。 - 借助 AI 录制、断言与验证(15.11.0)。Cypress Studio 可以通过录制应用中的真实操作来生成和扩展端到端测试。Studio AI 在此之上更进一步:录制过程中,它会观察 UI 的变化,自动推荐断言。你只需审核、保留合适的部分并保存。
- 在 Command Log 中隐藏 HTTP 请求(15.4.0)。如果不需要查看网络请求,可以直接从 Command Log 中隐藏它们。
- HTTP QUERY 方法(15.20.0)。
cy.request()和cy.intercept()现已支持 HTTP QUERY 方法。此前该方法在浏览器中会被判定为无效而被拒绝。 cy.press()支持 Escape 键。可以模拟按下 Escape 键,在浏览器中触发关闭和取消行为。--pass-with-no-tests命令行参数(15.11.0)。未找到任何 spec 文件时以成功码退出。适用于 CI 流水线中 spec 文件按条件生成或被过滤掉的场景。- 检测录制期间因 Cloud API 错误导致的失败(15.5.0)。启用
--posix-exit-codes后,当 Cypress 因网络错误而无法连接 Cypress Cloud 时,可以返回额外的退出码。 - 组件测试支持
experimentalRunAllSpecs(15.9.0)。experimentalRunAllSpecs选项现在不仅可用于 e2e 测试,也可用于组件测试。 - 支持 Bun 包管理器(15.17.0)。cypress npm 包现在可以通过 Bun 安装和调用。
- Firefox 中的视频录制(15.17.0)。视频录制功能现可在 Firefox 中正常生成视频。
性能优化
- 修复了嘈杂应用导致的崩溃(15.19.0, 15.18.0)。ResizeObserver 在每一动画帧中触发循环,或同一未捕获异常反复抛出,都可能耗尽内存。现在,重复的相同异常会合并为一条命令日志条目。
- 解决了文本密集页面的渲染器崩溃问题(15.20.0)。可见性检查原本对每个 overflow-hidden 祖先节点都序列化一次元素的整个文本子树,这可能耗尽渲染器内存并导致浏览器崩溃。
- 移除了每条浏览器消息的内存泄漏(15.19.0)。Cypress 发送给 Chromium 浏览器的每条消息都会泄漏少量内存,直到 spec 结束。对于长时、命令密集或网络密集的 spec,仅凭此泄漏就足以导致崩溃。
- 清理了 Open 模式下的内存占用(15.14.1, 15.14.0)。每次重新运行 spec 都会保留上一次的 Mocha runner 及其引用的所有内容,且在测试超出
numTestsKeptInMemory保留范围后,命令日志数据仍未及时释放。 - 让迟缓的命令日志重新变得迅捷(15.17.0, 15.14.2, 15.7.1)。悬停长测试时会触发列表中所有命令的样式重计算,滚动时注册了重复监听器,而在快照中高亮元素时执行了多余的样式工作。
- 消除了 CI 流程中的浪费(15.20.0, 15.13.1, 15.5.0)。内存采样会在资源受限的容器中生成辅助子进程,
cypress run会发起 GUI 专属的 git 调用,而 spec 切换时的存储清理也超出了必要范围。
大量 Bug 修复。在 Cypress 15 的生命周期内,我们关闭了超过 200 个 issue。您可以在 Cypress 应用更新日志中查看所有修复内容。
关于 Cypress 16 的常见问题
Cypress 16 是否为破坏性版本?是的。它移除了多个长期弃用的 API,变更了部分默认值,并提高了 Node.js、Vite 和 Angular 的最低版本要求。所有变更均在 Cypress 16 迁移指南中附有迁移步骤。
Cypress 16 有哪些完整变更? 完整的变更日志位于Cypress App Changelog。
有 Cypress 16 的迁移指南吗? 有Cypress 16 迁移指南,其中包含一段现成的提示词(Prompt),可引导你的 AI 编码助手完成迁移流程。
Cypress 支持 HTTP/2 吗? 支持,自 Cypress 16 起。在基于 Chromium 的浏览器(如 Chrome、Chromium 和 Edge)中,默认启用 HTTP/2。Electron、Firefox 和 WebKit 仍使用 HTTP/1.1。
Cypress 支持 HTTP/3 吗? 支持,自 Cypress 16 起。在 Chrome、Chromium 和 Edge 中,你的应用会直接连接服务器,并协商服务器支持的任意协议(包括 HTTP/3),这与生产环境的行为完全一致。如果你的服务器向真实用户提供了 HTTP/3 服务,那么测试时使用的也是该协议,无需额外配置。Electron、Firefox 和 WebKit 仍使用 HTTP/1.1。
我需要修改测试用例以使用 HTTP/2 吗? 不需要。当服务器支持时,请求会自动使用 HTTP/2。
HTTP/2 会改变 cy.intercept() 的工作方式吗?API 完全不变。匹配、stub、修改和等待请求的方式和以前一样,绝大多数测试套件无需任何改动。在底层,Chrome、Chromium 和 Edge 现在在浏览器原生网络层上拦截流量,因此少数传输层细节的呈现有所不同:req.httpVersion 不再返回,content-encoding 等压缩头不再出现在响应中(响应体已解码),重新验证的响应会返回 200 而不是 304,而由于 HTTP/2 和 HTTP/3 不携带 reason phrase,res.statusMessage 在这两种协议下是空字符串。对响应体、状态码和应用行为的断言照常生效,Firefox、WebKit 和 Electron 不受影响。每处差异都在原生网络拦截指南中有前后对比示例说明。
Cypress 16 会让我的测试更快吗?这取决于你的测试时间花在哪里。如果测试套件涉及大量请求的页面、频繁输入、大量可见性断言,或长时间运行导致内存吃紧,收益最明显。但如果慢的原因是长时间等待、重复的 UI 登录或真实网络调用,这些瓶颈并未改变,建议先阅读测试性能指南。
为什么移除 Cypress.env()?这是因为 Cypress.env() 会把所有 Cypress 环境变量注入浏览器上下文,包括测试可能永远不会读取的值,容易在无意中暴露不该暴露的数据。详情请阅读我们关于迁移到 cy.env() 和 Cypress.expose() 的博客文章。
为什么移除了 cy.exec?cy.task 可以完成 cy.exec 的所有功能,且 cy.task 在 Node 环境中运行,不依赖运行 Cypress 的机器的操作系统、shell 或终端。这简化了在 Node 中运行代码的支持,并消除了因环境差异导致的 cy.exec 中的 bug。
Cypress 16 中移除了 Electron 浏览器吗?没有。Electron 已被弃用,选择时会给出警告,但仍能运行测试。移除功能将在未来某个尚未排期的主要版本中进行。阅读我们关于“Electron 浏览器在 Cypress 中被弃用”的博文,了解弃用原因及迁移方法的详细信息。
为什么不能用 Cypress.config 设置 viewportWidth 和 viewportHeight?通过 Cypress 配置设置 viewport 宽高会导致意外行为:它实际改变的是下一个测试而非当前测试的视口大小。如果正在录制,视口变化也不会反映在 Test Replay 中。请改用 cy.viewport(),或在 describe、context 或 it 块的测试配置中设置 viewportHeight 和 viewportWidth。
为什么不能用 Cypress.config 设置 blockHosts?通过 Cypress.config 设置 blockHosts 会导致意外行为——它实际影响的是下一个测试而非当前测试。请改在 describe、context 或 it 块的测试配置中设置 blockHosts。
在 Cypress 16 中如何让测试输入像真实用户一样?Cypress 16 中,输入操作的默认延迟设置为 0ms。你可以通过 Cypress.Keyboard.defaults API 的 keystrokeDelay 选项将其恢复为 10ms 或其他任意数值,也可以向 cy.type() 传入 delay 参数。
Cypress.Keyboard.defaults({
keystrokeDelay: 10,
})
cy.get('input').type('slow typing', { delay: 10 })experimentalMemoryManagement 配置项被什么取代了? 在 Cypress 16 中,experimentalMemoryManagement 配置被 manageBrowserMemory 取代,默认值为 true。测试运行期间,Cypress 会按固定间隔采样浏览器的内存占用,并仅在采样值超过内存阈值时,强制在下个测试启动前执行垃圾回收。
该标志并非通用的性能优化。测试间清理内存需要时间,这笔开销会在每次测试切换时产生。如果你的测试套件未承受显著的内存压力,可以选择禁用该选项以避免额外开销。建议在禁用该标志前后分别测量性能影响。
为什么在 Cypress 16 中测试因“元素不可见”而失败? Cypress 16 调整了默认的元素可见性策略,使其更准确、可靠且高效。这一变更可能影响现有的可见性断言。当现代算法导致测试失败时,建议更新断言,以与算法无关的方式验证相同的用户可见行为。在迁移测试期间,可设置 visibilityStrategy: 'legacy' 以沿用旧的可见性策略。完整细节及迁移技巧请参阅 可见性策略文档。
为什么 Cypress.Commands.overwrite('getCookie', ...) 在 Cypress 16 中失效? 因为 cy.getCookie()、cy.getCookies()、cy.getAllCookies()、cy.getAllLocalStorage() 和 cy.getAllSessionStorage() 现为查询命令,重写它们需使用 Cypress.Commands.overwriteQuery() 而非 Cypress.Commands.overwrite()。
Cookie 命令的超时机制是否有变化? Cookie 和存储的读取操作现在与其他查询一样使用 defaultCommandTimeout,而不再使用 responseTimeout。Cookie 操作类命令(如 cy.setCookie())仍使用 responseTimeout。若读取需要更多时间,可在命令或链式断言中显式传入超时选项。
Cypress 16 的组件测试支持哪些框架版本?组件测试支持 Angular 21 和 22(包括无 zone 应用)、Vite 8,以及 Next.js 15 和 16。Angular 18 到 20、Vite 5 到 7、Next.js 14 已不再支持。