跨境延迟下两种模式耗时对比
2026 年主流流水线已普遍钉在 Node 22 LTS 或更高;在 arm64 的 Apple Silicon runner 上,CPU 解压与哈希 rarely 是瓶颈,跨境 RTT、TLS 与小包并发才是。Yarn Berry 的 PnP 将依赖以 Zip 形式缓存并按需映射,冷启动时往往表现为「更少小文件写入、更多集中式 Zip 拉取」;classic node_modules(nodeLinker: node-modules)则产生海量小文件与深层路径,磁盘与 inode 压力大,但在生态兼容性上更保守。二者谁更快没有绝对答案:请以同一 yarn.lock、同一镜像端点、各跑至少五次取 P95,再写入架构决策记录。
| 维度 | Yarn Berry PnP | classic node_modules |
|---|---|---|
| 冷启动特征 | 集中拉 Zip、落盘体积通常更小 | 大量 tarball 解压与小文件 scatter write |
| 跨境敏感点 | 对 registry 与 CDN 的长连接稳定性更敏感 | 对部分老旧 postinstall 脚本兼容更好 |
| 混合仓(iOS + JS) | 需确认 Fastlane/CocoaPods 周边工具链不依赖「物理 node_modules 路径」假设 | 与多数「复制 node_modules 进产物」教程兼容 |
| 缓存键设计 | 可优先缓存 .yarn/cache 与 .pnp.cjs |
常缓存整个 workspace 的 install 树,键变更频繁则易失效 |
共享 runner 的磁盘与并发策略可交叉对照 构建池并发与磁盘 FAQ。
.yarnrc.yml 与 .npmrc 参数(registry 镜像与并发安装)
下列清单可直接粘贴进评审备注或 Runbook,按环境替换域名与令牌注入方式(切勿把明文 token 提交进 Git)。
| 键 / 环境变量 | 建议值 / 说明 |
|---|---|
npmRegistryServer(.yarnrc.yml) |
指向企业可审计的 registry 镜像根;与 lockfile 中 tarball 解析域一致 |
networkConcurrency |
跨境场景常见起点 8–16;遇 429 再降到 4–8 并加长退避 |
httpTimeout |
弱网可调至 600000 ms 量级;配合日志区分「慢」与「死」 |
enableGlobalCache |
多 Job 同机时谨慎共享全局缓存目录,建议每 runner 子目录 + 文件锁 |
nodeLinker |
pnp 与 node-modules 二选一写死;避免本地与 CI 混用未声明默认 |
.npmrc registry= |
与 Yarn 声明一致;若工具链仍读 npm 配置,保持双写以免漂移 |
可执行骨架(CI 步骤内):
GitHub Packages 与 npm 双源认证及 token 轮换
私有作用域包常落在 GitHub Packages,而公共依赖仍走 npm:请在 .yarnrc.yml 使用 npmScopes / npmRegistries 将 @org 绑定到 npm.pkg.github.com,默认 registry 仍指向镜像或 npmjs。认证令牌应来自 CI 密钥存储(OIDC 优先于长期 PAT),并设只读与短 TTL;轮换流程建议:新令牌入库 → 灰度一条 pipeline → 全量切换 → 吊销旧令牌。always-auth 与作用域级 _authToken 仅通过环境变量注入,避免写入仓库。
CI 并行度与磁盘水位阈值
Apple Silicon 上并行 yarn install 与 Xcode 派生数据并存时,磁盘尾延迟陡增。建议:同一物理 runner 上 install 阶段默认串行或 Semaphore=1;bootstrap 完成后再放大测试分片。剩余空间阈值可与站内矩阵对齐——重度 monorepo 建议 bootstrap 前 ≥18 GiB,中等 ≥12 GiB,低于则 fail fast 或改走只读缓存卷。
失败重试与 lockfile 一致性验收
网络类失败采用 2s / 4s / 8s 退避最多 三轮;每轮打印当前 registry 主机与 YARN_ENABLE_IMMUTABLE_INSTALLS 状态。lockfile 一致性验收:CI 必须执行 yarn install --immutable(或等价环境变量),任何 lockfile 漂移直接失败而非静默改写;合并请求上附带 yarn.lock 与 .yarnrc.yml 的 diff 摘要。重试通过后应用校验:再次以只读模式安装,耗时应收敛且无「重新 fetch 全部包」日志。
FAQ
PnP 下 React Native / Metro 报错找不到模块?
优先查阅官方 PnP 兼容插件与 SDK 版本;若短期无法收敛,可在 CI 单独使用 nodeLinker: node-modules 的 profile,与本地开发文档写清差异。
镜像与上游 tarball 哈希不一致?
检查镜像是否改写压缩格式或截断 Range;对安全基线要求高的团队,建议镜像仅做透传加速并保留上游校验元数据。
是否应升级到 Yarn 4?
以 lockfile 与插件兼容为准;升级前后各跑一轮完整 install + 单测,并把 Node 与 Yarn 主版本写入 runner 标签,避免「同一池子混跑」造成隐性漂移。