构建门控
确保代码在 CI 中编译构建后才能合并、抓本地环境漏的集成错。
为什么
"我机器上工作"是软件工程最著名短语有因——开发者本地环境有特定 Node 版本、特定 OS、不在仓的环境变量和月前装的依赖。CI 有干净环境、.nvmrc 的确切 Node 版本、package-lock.json 的确切依赖、无本地状态。构建门控在这干净环境跑构建抓本地环境漏的集成错: 因旧缓存本地工作的导入、在 devDependencies 但生产用的依赖、本地设但 CI 未设的环 境变量。构建门控是代码真编译集成的第一证——无它团队在生产(或发管道太晚)发现构建失败。3 分钟每 PR 跑的构建门控是防"我机器上工作" bug 最便宜保险。
何时使用
每 PR、合前——构建门控是代码编译集成的最低证。
如何做
1. 干净 CI 环境跑构建 - 用 .nvmrc/.python-version 的确切 Node/Python/Java 版本 - 从锁文件装依赖(npm ci、pip install -r requirements.txt) - 不用开发者机器缓存的 node_modules - 这抓"我机器上工作" bug 2. 构建生产产物非仅开发构建 - npm run build(生产构建非开发服务器) - 这抓仅生产问题(摇树优化、环境变量) - 开发构建工作但生产构建失败是 bug 3. 多平台构建(若部署到多) - 矩阵构建: [ubuntu-latest、windows-latest、macos-latest] - 这抓平台特定问题(路径分隔符、原生模块) - 若仅部署 Linux 则仅 Linux 构建 4. 缓存构建依赖(但不缓存构建输出) - 缓存 node_modules(加速 npm ci) - 不缓存 dist/(构建须新鲜跑抓错) - 缓存 .next/cache 或 target/(增量构建产物) 5. 构建错快失败 - 构建门控应首次错立即失败 - 不在坏构建上继续跑测试 - 错误消息应清: 哪文件、哪行、什么错 6. 要求构建门控合前过 - 分支保护: 要求构建作业 过 - 构建失败不允许合 - 这防坏构建到 main
示例
# .github/workflows/ci.yml — 构建门控
name: CI
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20] # 测多 Node 版本
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm # 缓存 node_modules
- run: npm ci # 从锁文件装(非 npm install)
- run: npm run build # 生产构建
- run: npm run typecheck # tsc --noEmit
# .nvmrc — 固定 Node 版本
20
# package.json — 构建脚本
{
"scripts": {
"build": "next build", // 生产构建
"typecheck": "tsc --noEmit",
"dev": "next dev" // 开发服务器(CI 不用)
}
}
# 门控抓的常见构建错:
# 1. 导入错: 本地工作(旧缓存)但 CI 失败
# 错: 找不到模块 './utils' 或其对应类型声明
# 修: 导入路径错或文件未提交
# 2. 类型错: 本地工作(未跑 tsc)但 CI 失败
# 错: 类型 'User' 上不存在属性 'name'
# 修: 类型错或属性可选
# 3. 环境变量错: 本地工作(.env 设)但 CI 失败
# 错: 缺环境变量: DATABASE_URL
# 修: 加环境变量到 CI 工作流或仓密
# 4. 依赖错: 本地工作(node_modules)但 CI 失败
# 错: 找不到包 'lodash'
# 修: 依赖不在 package.json 或在 devDependencies
# 但生产代码用
# 分支保护: 要求构建门控
# 设置 > 分支 > 分支保护规则:
# - 要求状态检查过: build
# - 合前要求分支最新常见问题
- ⚠CI 中用 npm install 非 npm ci——npm install 更新锁文件装与开发者不同版本、CI 构建过但生产失败(或反)因依赖不同。
- ⚠缓存构建输出(dist/)非仅依赖——构建因输出缓存跳、新鲜构建会抓的构建错漏、坏代码合。
- ⚠应用部署多平台但仅一平台构建——Linux 构建过但 Windows 因路径分隔符失败、团队生产发现。
- ⚠CI 仅跑开发构建非生产构建——开发构建跳摇树优化、环境变量验证和压缩、生产构建失败于开发构建未抓的问题。
最佳实践
- ✓干净 CI 环境用 npm ci(非 npm install)跑生产构建(npm run build)——这抓本地环境漏的"我机器上工作" bug。
- ✓缓存依赖(node_modules)不缓存构建输出(dist/)——构建须新鲜跑抓错但依赖装可缓存加速。
- ✓若部署多平台在所有目标平台(Linux、Windows、macOS)构建——这抓路径分隔符和原生模块兼容性等平台特定问题。
- ✓分支保护要求构建门控合前过不允许绕——main 上坏构建阻整个团队、修比 PR 中抓贵 10 倍。