关于 build-engineer
此构建工程 Skill 涵盖 monorepo 工具、打包器和增量构建实践,帮助开发者选择工具、优化 CI、分析依赖并排查常见构建问题。
主要功能
- 01比较 monorepo 工具与打包器
- 02指导远程缓存和并行构建
- 03涵盖 Nx 受影响任务工作流
- 04讲解 Bazel 构建概念
- 05识别依赖与 CI 常见问题
适用场景
- 01为 monorepo 项目选择工具
- 02减少缓慢 CI 流水线的工作量
- 03从 Webpack 迁移到 Vite 或 Rspack
- 04诊断循环依赖或未声明依赖
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ 404kidwiz/ claude-supercode-skills --skill build-engineer安装后在 Claude Code 中输入/build-engineer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/best_practices.mdbundler_guide.mdframework_selection.mdoptimization_strategies.mdtroubleshooting.mdscripts/code_splitting.pyconfig_vite.pyconfig_webpack.pydev_server.pyoptimize_cache.pyoptimize_production.py详细介绍
构建工程师
用途
提供构建系统和 CI/CD 优化方面的专业知识,专注于单体仓库工具(Turborepo、Nx、Bazel)、打包器优化(Webpack/Vite/Rspack)和增量构建。通过缓存、并行化和构建性能优化,提升开发效率。
适用场景
- 设置单体仓库(pnpm workspaces + Turborepo/Nx)
- 优化缓慢的 CI 构建(远程缓存、分片)
- 为提升性能从 Webpack 迁移到 Vite/Rspack
- 配置高级 Bazel 构建规则(Starlark)
- 调试复杂的依赖关系图或循环依赖
- 实现“受影响”构建(仅测试发生变更的部分)
2. 决策框架
单体仓库工具选择
| 工具 | 最适用于 | 优点 | 缺点 |
|---|---|---|---|
| Turborepo | JS/TS 生态系统 | 零配置、简单、原生支持 Vercel。 | 主要仅支持 JS,粒度不如 Bazel。 |
| Nx | 企业级 JS/TS | 强大的插件、代码生成、依赖关系图可视化。 | 配置较重,观点鲜明。 |
| Bazel | 多语言(Go/Java/JS) | hermetic 构建,无限扩展能力(Google 风格)。 | 学习曲线陡峭,设置复杂。 |
| Pnpm Workspaces | 简单项目 | Node.js 原生支持,安装速度快。 | 不负责任务编排(需要 Turbo/Nx)。 |
打包器选择
What is the priority?
│
├─ **Development Speed (HMR)**
│ ├─ Web App? → **Vite** (ESModules based, instant start)
│ └─ Legacy App? → **Rspack** (Webpack compatible, Rust speed)
│
├─ **Production Optimization**
│ ├─ Max Compression? → **Webpack** (Mature ecosystem of plugins)
│ └─ Speed? → **Rspack / Esbuild**
│
└─ **Library Authoring**
└─ Dual Emit (CJS/ESM)? → **Rollup** (Tree-shaking standard)
危险信号 → 升级给 devops-engineer:
- CI 流水线耗时 > 20 分钟
node_modules大小 > 1GB(幽灵依赖)- “在我的机器上可以运行”,但在 CI 中失败(环境漂移)
- 在构建产物中发现密钥(Source maps)
4. 核心工作流
工作流 1:设置 Turborepo(远程缓存)
目标: 通过复用缓存产物,将 CI 耗时缩短 80%。
步骤:
-
配置(
turbo.json){ "$schema": "https://turbo.build/schema.json", "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**", ".next/**"] }, "test": { "dependsOn": ["build"], "inputs": ["src/**/*.tsx", "test/**/*.ts"] }, "lint": {} } } -
远程缓存
- 连接到 Vercel Remote Cache:
npx turbo link。 - 在 CI(GitHub Actions)中:
env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
- 连接到 Vercel Remote Cache:
-
执行
turbo run build test lint- 首次运行:5 分钟。第二次运行:100ms(FULL TURBO)。
工作流 3:Nx 受影响项目命令
目标: 在单体仓库中仅运行发生变更的项目的测试。
步骤:
-
分析依赖关系图
nx graph(可视化依赖关系:App A 依赖 Lib B)。
-
CI 流水线
# 仅测试受 PR 影响的项目 npx nx affected -t test --base=origin/main --head=HEAD # 仅检查受影响项目的代码风格 npx nx affected -t lint --base=origin/main
工作流 5:面向 JS 开发者的 Bazel 概念
目标: 理解 BUILD 文件与 package.json 的区别。
对应关系:
| NPM 概念 | Bazel 概念 |
|---|---|
package.json | WORKSPACE / MODULE.bazel |
script: build | js_library(name = "build") |
dependencies | deps = ["//libs/utils"] |
node_modules | npm_link_all_packages |
代码示例(BUILD.bazel):
load("@aspect_rules_js//js:defs.bzl", "js_library")
js_library(
name = "pkg",
srcs = ["index.js"],
deps = [
"//:node_modules/lodash",
"//libs/utils"
],
)
5. 反模式与注意事项
❌ 反模式 1:幽灵依赖
表现:
import foo from 'foo'在本地可以运行,但在 CI 中失败。
失败原因:
- 包管理器提升了 'foo',但它未列在
package.json中。
正确做法:
- 使用 pnpm(严格模式)。它通过符号链接阻止访问未声明的依赖。
❌ 反模式 2:循环依赖
表现:
- Lib A 导入 Lib B。Lib B 导入 Lib A。
- 构建失败,并提示 "Maximum call stack exceeded" 或 "Undefined symbol"。
失败原因:
- 架构中的逻辑错误。
正确做法:
- 提取共享代码: 将通用逻辑移至 Lib C。
- A → C,B → C。
- 使用
madge工具检测循环依赖:npx madge --circular .
❌ 反模式 3:提交 node_modules
表现:
- Git 仓库大小达到 2GB。
失败原因:
- 克隆速度慢。特定平台的二进制文件会导致问题。
正确做法:
.gitignore必须包含node_modules/、dist/、.turbo/、.next/。
7. 质量检查清单
性能:
- 缓存: 已启用并验证远程缓存(命中率 > 80%)。
- 并行执行: 尽可能并行运行任务(感知拓扑结构)。
- 体积: 生产构建产物已压缩并进行 tree-shaking。
可靠性:
- 锁文件:
pnpm-lock.yaml/package-lock.json保持一致。 - CI: 在干净的运行器上构建通过(无缓存)。
- 确定性: 相同的输入 = 相同的哈希值。
可维护性:
- 脚本:
package.json脚本已标准化(dev、build、test、lint)。 - 依赖图: 依赖图无环(DAG)。
- 脚手架: 已配置用于创建新库/应用的生成器。
示例
示例 1:企业级 Monorepo 迁移
场景: 一家拥有 500 名开发者、4 个 React 应用和 15 个共享库的公司,希望从独立仓库迁移到 Monorepo,以改进代码共享和 CI 效率。
迁移方法:
- 工具选择: 选择 Nx,以使用其企业级功能和依赖图可视化能力
- 依赖映射: 使用 madge 可视化项目间的当前依赖关系
- 模块边界: 定义清晰的分层(ui、utils、data-access、features)
- 构建优化: 使用 Nx Cloud 配置远程缓存
迁移结果:
- CI 构建时间从 45 分钟缩短至 8 分钟(提升 82%)
- 通过共享库将代码重复减少 60%
- 受影响的构建只测试发生变更的项目(通常不到 1 分钟)
- 通过 Nx 项目推断强制执行清晰的架构边界
示例 2:从 Webpack 迁移到 Rspack
场景: 某大型电子商务平台因 Webpack 配置复杂,生产构建速度较慢(12 分钟),希望改善开发者体验。
迁移策略:
- 渐进式迁移: 从开发构建开始,暂时保留 Webpack 用于生产构建
- 配置转换: 将 Webpack loader 映射为对应的 Rspack 配置
- 插件兼容性: 使用 rspack-plugins 支持兼容 webpack 的插件
- 验证: 运行并行构建,验证输出是否一致
性能对比:
| 指标 | Webpack | Rspack | 提升 |
|---|---|---|---|
| 开发服务器启动 | 45s | 2s | 96% |
| HMR 更新 | 8s | 0.5s | 94% |
| 生产构建 | 12m | 2m | 83% |
| Bundle 大小 | 2.4MB | 2.3MB | 4% |
示例 3:采用分片的分布式 CI 流水线
场景: 一家拥有 5,000 个 E2E 测试的游戏公司,需要将 CI 时间从 90 分钟缩短至 15 分钟以内,以便快速获得反馈。
流水线设计:
- 测试分析: 按耗时和并行潜力对测试进行分类
- 分片策略: 将测试拆分为 20 个分片,每个分片运行约 250 个测试
- 智能调度: 使用 Nx affected,仅运行变更功能对应的测试
- 资源优化: 配置自动扩缩容的运行器,以并行执行
CI 流水线配置:
# GitHub Actions with Playwright sharding
- name: Run E2E Tests
run: |
npx playwright test --shard=${{ matrix.shard }}/${{ matrix.total }} \
--config=playwright.config.ts
strategy:
matrix:
shard: [1, 2, ..., 20]
max-parallel: 10
结果:
- E2E 测试耗时:90m → 12m(提升 87%)
- 开发者反馈周期缩短至 15 分钟以内
- 通过改进并行执行,将云端 CI 成本降低 30%
最佳实践
Monorepo 架构
- 明确边界:从一开始就建立并落实项目边界
- 采用严格的依赖规则:防止循环依赖并确保依赖方向正确
- 自动创建项目:使用生成器,以统一的方式设置新项目
- 统一管理软件包版本:使用 Changesets 或 Lerna 协调发布
- 记录依赖关系:维护架构决策记录,记录变更
构建性能
- 先分析再优化:使用 speed-measure-webpack-plugin 等工具找出瓶颈
- 增量构建:配置构建工具,只重新构建必要的部分
- 并行执行:利用可用的 CPU 核心并行执行任务
- 缓存策略:在各个层级实施积极的缓存策略
- 依赖优化:定期清理未使用的依赖(bundlephobia)
CI/CD 卓越实践
- 快速失败:优先运行快速测试,尽早发现失败
- 分片策略:合理地将测试分配到多个运行器
- 缓存所有内容:依赖、构建产物、测试结果
- 按需执行:只运行受变更影响的任务
- 将流水线作为代码:将 CI 配置与代码一同纳入版本控制
工具选择
- 让工具匹配技术生态:不要强行使用不适合技术栈的工具
- 评估迁移成本:考虑总成本,而不只是性能提升
- 社区活跃度:选择维护活跃且有社区支持的工具
- 插件生态:确保提供所需的集成
- 团队熟悉度:考虑学习曲线和团队采纳情况
安全与合规
- 密钥扫描:绝不提交密钥;使用自动化扫描
- 依赖审计:定期扫描漏洞并自动修复
- 访问控制:将 CI 凭据的权限限制在最低必要范围
- 构建可复现性:确保可以从源代码复现构建
- 审计日志:保留所有构建和部署活动的日志
评论
支持 Markdown