首页
/ Cypress 发布产物构建指南:npm 包与 Electron 二进制的构建、打包与发布流程

Cypress 发布产物构建指南:npm 包与 Electron 二进制的构建、打包与发布流程

2026-09-05 10:41:24作者:郦嵘贵Just

本篇围绕 Cypress 仓库中的构建指南 building-release-artifacts.md 展开,讲清 Cypress 发布产物的两大组成——npm 包与二进制压缩包——各自如何构建、打包与验证。读完你能掌握 yarn lerna run build-cliyarn binary-buildyarn binary-packageyarn binary-zip 等命令的完整用法与适用平台限制,并能结合 scripts/binary/build.tsscripts/binary/zip.js 等源码理解产物内部的组装过程。

发布产物的整体结构

Cypress 的 cypress npm 包由两部分组成,二者必须保持同一版本号:

  1. npm 包 .tgz(由 cli 目录构建)
    • 包含命令行工具 cypress、TypeScript 类型定义和 Module API;
    • 最终用户通过 npm/Yarn/pnpm 将其安装到项目的 node_modules 目录。
  2. "二进制" .zip(由 packages 目录构建)
    • 包含 Electron 应用、ffmpeg,以及 packages 子目录中各包的构建产物(frontend-sharedreporterweb-config 不单独打包进去);
    • 同时包含上述所有包的生产依赖;
    • cli 安装时或执行 cypress install 时被下载到系统缓存目录;生产环境下若本地未缓存,会从 Cypress CDN 拉取。

该指南覆盖了这两种产物的构建方式,并额外提供了打包、冒烟测试、上传与缓存清理等配套流程。

构建 npm 包

指南原文特别提示:以下两步在 CI 中已自动化,按正式发布流程(见 release-process.md)走时不需要你手动执行。

构建一个 npm 包只需要两步:

  1. 递增根 package.json 中的 version
  2. 运行 yarn lerna run build-cli

这两步实际完成的工作:

  • 构建 cypress npm 包;
  • 将代码转译为 ES5,以兼容常见的 Node 版本;
  • 结果输出到 cli/build 目录。

从源码看,build-cli 脚本定义在 cli/package.json 中:

"build": "rollup -c",
"postbuild": "yarn make-bin-executable && yarn sync-build-dist && yarn prepare-package-json && yarn bundle-ct-frameworks",
"build-cli": "rollup -c && yarn postbuild",

即先用 cli/rollup.config.mjs 完成 Rollup 打包,随后依次执行 bin 可执行化处理、产物同步、package.json 准备(cli/scripts/prepare-package-json.ts)与组件测试框架的框架打包(cli/scripts/bundle-ct-frameworks.ts),保证 npm 包内容完整可发布。

构建二进制

同样地,二进制的构建步骤在 CI 中已自动化。npm 包必须有同版本的二进制与之对应,生产环境下若本地未缓存会从 CDN 检索。本地构建的入口命令(见根 package.jsonscripts):

命令 作用 脚本定义
yarn binary-build 构建二进制 cross-env NODE_OPTIONS=--max_old_space_size=8192 node ./scripts/binary.js build
yarn binary-package 打包(electron 打包)二进制 cross-env NODE_OPTIONS=--max_old_space_size=8192 node ./scripts/binary.js package
yarn binary-zip 将构建好的二进制压缩为 zip node ./scripts/binary.js zip
yarn binary-smoke-test 对构建产物做冒烟测试 node ./scripts/binary.js smoke
yarn binary-deploy build → zip → upload 一条龙 node ./scripts/binary.js deploy
yarn binary-purge 清理某版本各平台的 CDN 缓存 node ./scripts/binary.js purge-version

注意 binary-buildbinary-package 都通过 cross-env 注入了 NODE_OPTIONS=--max_old_space_size=8192,因为构建过程内存占用较高。

平台选择:可以在 Linux 上构建 Cypress 二进制(与 CI 相同的方式)——在 yarn docker 容器内运行 yarn binary-buildyarn binary-package。仓库根目录提供了 docker-compose.yml 支撑该容器环境。

macOS 本地构建:需要在钥匙串中拥有代码签名证书(按 Apple 官方代码签名指南申请)。另外,由于公证(notarization)需要 Apple Developer Program 账号,本地构建时通常应设置 SKIP_NOTARIZATION=1 跳过公证。CI 中的代码签名细节见 code-signing.md

构建阶段内部做了什么(源码级解读)

yarn binary-build 最终调用 scripts/binary/index.jsdeploy.build,再进入 scripts/binary/build.tsbuildCypressApp。其流程与源码注释高度对应:

  • 禁止交叉构建if (platform !== os.platform()) 直接抛错,"Attempting to cross-build, which is not supported"——这正是指南要求"在哪个平台构建哪个平台产物、或用 docker 构建 Linux 版"的底层原因(见 scripts/binary/build.ts#L77-L80);
  • 清理与符号链接:删除 TMP_BUILD_DIRbuild/packages/electron/dist,并将 build 符号链接到系统临时目录下的 cypress-build/<platform>/build(路径常量定义在 scripts/binary/meta.tsTMP_BUILD_DIRbuildRootDir);
  • 构建各子包:把目标 version 写回根 package.json(保证 V8 快照与版本正确),然后并发执行 yarn lerna run buildyarn lerna run build-prod,并发度为 min(4, os.availableParallelism())
  • 拷贝到 distpackages.copyAllToDist 把各包产物拷贝进 dist 目录,并拷贝 patches 目录(过滤掉 .dev.patch,因为生产安装只会应用生产补丁),同时拷贝 yarn.lock 保证安装一致性;
  • 精简生产依赖:剔除 devDependencieslint-staged 等字段后写入 dist 的 package.jsonpostinstall 只保留 patch-package,再执行 yarn --production
  • 瘦身:用 del 删除各依赖包中的测试目录(如 pixelmatch/testexif-parser/test 等)、.ts 源文件与开发用补丁;
  • 写入运行时入口:生成 dist 的 index.jsrequire('./packages/server/index.js'))与包含 electronVersion/electronNodeVersionpackage.json
  • 构建后自验证testDistVersion 在 dist 目录执行 node index.js --version 并与目标版本比对,testStaticAssets 校验静态资源,任何不一致都会让构建失败。

yarn binary-package 则调用 packageElectronAppscripts/binary/build.ts#L237):

  • 移除 node_modules/.bin、开发用 Electron 应用目录等打包后无用的内容;
  • 通过 electron-builderpublish: 'never'asar: false 配置进行应用打包(注释说明因 electron-builder 不会拷贝 packages/*/node_modules 中的嵌套目录,故不使用 asar);
  • Windows 路径长度防护checkMaxPathLength 按"默认缓存位置 + 260 字符上限"检查 dist 内所有相对路径,超限即报错要求提升(hoist)或删除文件(scripts/binary/build.ts#L45-L70);
  • macOS GateKeeper 校验:当 platform === 'darwin' 且未跳过签名时,用 spctl -a -vvvv 验证应用签名,失败即抛 "Verifying App via GateKeeper failed"(scripts/binary/build.ts#L309-L326);
  • 最后用 du -d 1 统计各包大小并做性能追踪,便于控制 Test Runner 体积。

各平台产物目录约定由 scripts/binary/meta.ts 统一管理:macOS 为 build/mac(M1 为 build/mac-arm64)下的 Cypress.app,Linux 为 build/linux-unpacked(arm64 为 linux-arm64-unpacked),Windows 为 build/win-unpacked(见 meta.buildDir 实现)。

冒烟测试

构建完成后建议跑 yarn binary-smoke-test。对应 scripts/binary/index.jssmoke 方法:在无显示环境下自动启动 xvfb(xvfb.isNeeded()),然后执行 testExecutableVersion——调用构建产物的可执行文件加 --version(Linux 沙箱环境会追加 --no-sandbox),断言输出与构建版本一致,再对应用目录执行 scripts/binary/smoke.js 的冒烟测试。

打包(压缩)二进制

yarn binary-zip 的调用链是:deploy.zipmeta.zipDir(platform) 取待压缩目录 → zip.ditto(zipDir, zipPath)scripts/binary/zip.js 按平台分派三种压缩工具:

平台 工具 命令要点
Linux zip cd <父目录> && zip -r9 <dest> Cypress(先 renameFolder 确保顶层目录名为 Cypress
macOS ditto ditto -c -k --sequesterRsrc --keepParent <src> <dest>,保留资源分叉并保留顶层目录
Windows 7-Zip 7z a <dest> <src>,整个目录(含顶层 Cypress/)压入

其中 Linux 与 Windows 路径在压缩后会执行 checkZipSizescripts/binary/zip.js#L70-L84):

const MAX_ALLOWED_SIZE_MB = os.platform() === 'win32' ? 295 : 256

zip 超过 256MB(Windows 295MB)直接抛错。源码注释特别叮嘱:修改这个上限前,先查清是什么导致了二进制体积增长,并在 PR 中说明。

发布流水线与 CDN 校验

yarn binary-deploy 走完整管线(scripts/binary/index.js#L417-L435):buildzipuploadupload 将 zip 上传到 S3 的指定路径(upload.getFullUploadPath),随后通过 scripts/binary/util/upload.js 清理该版本的 Cloudflare 缓存。

发布完成后还有两级 CDN 校验(release 流程):

  1. 清单校验checkManifest 拉取 download.cypress.io/desktop.json,确认 manifest.version 与发布版本一致;
  2. 下载校验checkDownloads 对 5 个平台/架构组合(linux-x64、linux-arm64、darwin-x64、darwin-arm64、win32-x64)逐一 HEAD 请求确认二进制存在;若有缺失,提示用 yarn binary-purge --version <v> 清理 Cloudflare 缓存后再用 yarn binary-ensure --version <v> 复查(见 scripts/binary/index.js#L177-L242)。

实用技巧(指南 Tips 原文)

  • 加速打包:设置 V8_SNAPSHOT_DISABLE_MINIFY=1 可缩短二进制打包耗时。从源码看,该开关在 V8 快照工具的 tooling/v8-snapshot/src/setup/config.ts#L95 中被读取:const minify = !process.env.V8_SNAPSHOT_DISABLE_MINIFY && env === 'prod',即跳过生产环境对快照的压缩步骤以换取速度;
  • M1 芯片:在 M1 Mac 上打包后若要实际运行该二进制,需要设置 RESET_ADHOC_SIGNATURE=1 来重置临时(adhoc)签名。

小结

Cypress 的发布产物由 npm 包与二进制 zip 双轨构成:npm 包只需递增版本并执行 yarn lerna run build-cli,产出进入 cli/build;二进制则通过 yarn binary-build(构建 dist 并做版本/静态资源自验证)、yarn binary-package(electron-builder 打包、平台签名与 GateKeeper 校验)、yarn binary-zip(平台化压缩并做体积上限检查)三步完成,再配合 binary-deploybinary-smoke-test 与 CDN 清单/下载校验形成完整闭环。所有环节在 CI 中已自动化,本地执行时按本文命令即可复现;平台限制(不支持交叉构建、macOS 需签名证书、Linux 可走 docker)是实操中最需要留意的约束。

登录后查看全文
热门项目推荐
相关项目推荐