Skill: wangzhiming1999/build-engineering (version 1.0.0)

--- name: build-engineering description: Optimizes build toolchain and engineering setup: Vite/Webpack config, Monorepo with pnpm/Turborepo, Module Federation, CI/CD pipeline, code generation, and DX improvements. Use when 构建优化, Monorepo, 模块联邦, CI/CD, 工程化, Vite, Webpack, Turborepo, or build config. model: opus --- # 构建与工程化（Build Engineering） 解决构建慢、包体积大、多包协作混乱、CI 不稳定等工程问题，让团队把时间花在业务上而不是工具上。 ## 触发场景 - 「构建太慢了」「热更新卡」「CI 跑 20 分钟」 - 「多个项目共享组件，怎么管理」「Monorepo 怎么搭」 - 「微前端怎么做」「模块联邦怎么配」 - 「bundle 分析完了，不知道怎么优化」 - 「代码生成」「自动化脚本」「工程规范落地」 --- ## 执行流程 ### 1. 先定位问题类型 | 用户描述 | 实际问题 | 第一步 | |---------|---------|-------| | 「构建慢」「dev 启动慢」 | 构建性能 | 问：用 Vite 还是 Webpack？冷启动多久？热更新多久？ | | 「多个项目共享代码」 | 代码共享架构 | 问：几个项目？是否需要独立发版？团队规模？ | | 「微前端」「模块联邦」 | 运行时集成 | 问：是独立部署还是同仓库？需要共享状态吗？ | | 「CI 太慢」「流水线不稳定」 | CI/CD 优化 | 问：用什么 CI？哪个步骤最慢？有没有缓存？ | | 「bundle 大」 | 产物优化 | 直接让用户跑分析工具，看报告再说 | ### 2. 构建性能优化 **Vite 项目慢的常见原因和解法：** | 问题 | 诊断方式 | 解法 | |------|---------|------| | 冷启动慢 | 看 `vite --debug` 输出 | 检查是否有大量 CommonJS 依赖需要预构建；用 `optimizeDeps.include` 预声明 | | 热更新慢 | 改一个文件，看 HMR 耗时 | 检查是否有循环依赖；大型组件库按需引入 | | 生产构建慢 | `vite build --profile` | 开启 `build.rollupOptions.output.manualChunks` 手动分包；关闭不需要的插件 | **Webpack 项目提速的优先级顺序：** 1. 升级到 Webpack 5（持久化缓存 `cache: { type: 'filesystem' }`） 2. 缩小 loader 处理范围（`include: path.resolve('src')`，排除 node_modules） 3. 开启多线程（`thread-loader` 用于 babel/ts 编译） 4. 用 `esbuild-loader` 替换 `babel-loader`（速度提升 10-20x） 5. 考虑迁移到 Vite（新项目首选，存量项目评估迁移成本） **不要做的事：** - 不要为了"优化"随意升级 Webpack 大版本，破坏性变更多 - 不要在没有 profile 数据的情况下盲目加插件 ### 3. Monorepo 架构决策 **什么时候需要 Monorepo：** - 3 个以上项目共享组件/工具/类型 - 需要原子提交（一个 PR 同时改多个包） - 团队需要统一的 lint/test/build 规范 **什么时候不需要：** - 项目完全独立，没有共享代码 - 团队 < 3 人，管理成本大于收益 **推荐方案（2025 年）：** ``` pnpm workspace + Turborepo ├── apps/ │ ├── web/ # 主应用 │ └── admin/ # 管理后台 ├── packages/ │ ├── ui/ # 共享组件库 │ ├── utils/ # 工具函数 │ ├── types/ # 共享类型 │ └── config/ # 共享配置（eslint���tsconfig、tailwind） ├── pnpm-workspace.yaml └── turbo.json ``` **Turborepo 关键配置：** ```json // turbo.json { "pipeline": { "build": { "dependsOn": ["^build"], // 先构建依赖包 "outputs": ["dist/**"] }, "test": { "dependsOn": ["build"], "outputs": [] }, "dev": { "cache": false, // dev 不缓存 "persistent": true } } } ``` **包之间的依赖声明：** ```json // apps/web/package.json { "dependencies": { "@myorg/ui": "workspace:*", "@myorg/utils": "workspace:*" } } ``` ### 4. 模块联邦（Module Federation） **适用场景：** 多个独立部署的应用需要在运行时共享组件或逻辑（微前端）。 **不适用场景：** 同一仓库的多个包——用 Monorepo 就够了，不需要模块联邦。 **Vite 模块联邦配置（`@originjs/vite-plugin-federation`）：** ```ts // 提供方（组件库应用）vite.config.ts import federation from '@originjs/vite-plugin-federation' export default { plugins: [ federation({ name: 'remote-app', filename: 'remoteEntry.js', exposes: { './Button': './src/components/Button.vue', './utils': './src/utils/index.ts', }, shared: ['vue', 'pinia'], // 共享依赖，避免重复加载 }) ], build: { target: 'esnext' } // 模块联邦需要 esnext } // 消费方 vite.config.ts export default { plugins: [ federation({ name: 'host-app', remotes: { 'remote-app': 'http://localhost:5001/assets/remoteEntry.js', }, shared: ['vue', 'pinia'], }) ] } ``` **模块联邦的坑：** - 共享依赖版本必须兼容，否则会加载两份 - 类型不会自动共享，需要单独处理（发布 `.d.ts` 或用 `@module-federation/typescript`） - 本地开发需要先构建提供方，或用 `vite preview` 模拟 ### 5. CI/CD 优化 **CI 慢的排查顺序：** 1. **缓存命中率**：`node_modules`、构建产物、测试结果是否有缓存？ 2. **并行化**：lint、test、build 能否并行跑？ 3. **增量执行**：只跑受影响的包（Turborepo `--filter` 或 `affected`） 4. **测试分片**：大型测试套件拆分到多个 runner 并行 **GitHub Actions 最佳实践：** ```yaml jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v3 with: { version: 9 } - uses: actions/setup-node@v4 with: node-version: 20 cache: 'pnpm' # 缓存 pnpm store - run: pnpm install --frozen-lockfile - name: Cache Turborepo uses: actions/cache@v4 with: path: .turbo key: turbo-${{ github.sha }} restore-keys: turbo- # 前缀匹配，复用历史缓存 - run: pnpm turbo build test --filter='[HEAD^1]' # 只跑有变更的包 ``` ### 6. 代码生成与自动化 **值得自动化的场景：** - 从 OpenAPI/Swagger 生成 API 类型和请求函数（`openapi-typescript` + `orval`） - 从设计 token 生成 CSS 变量和 Tailwind 配置（`style-dictionary`） - 新功能脚手架（`plop` 或自定义 CLI） **OpenAPI 代码生成示例：** ```bash # 安装 pnpm add -D openapi-typescript orval # 生成类型 npx openapi-typescript ./api/openapi.yaml -o ./src/types/api.d.ts # orval 生成 React Query hooks # orval.config.ts export default { api: { input: './api/openapi.yaml', output: { mode: 'tags-split', target: './src/api', schemas: './src/types', client: 'react-query', override: { mutator: { path: './src/lib/axios.ts', name: 'customInstance' } } } } } ``` **新功能脚手架（plop）：** ```js // plopfile.js export default function (plop) { plop.setGenerator('component', { description: '创建新组件', prompts: [ { type: 'input', name: 'name', message: '组件名称（PascalCase）' }, { type: 'list', name: 'type', choices: ['ui', 'feature', 'page'] } ], actions: [ { type: 'add', path: 'src/components/{{name}}/index.tsx', templateFile: 'plop-templates/component.hbs' }, { type: 'add', path: 'src/components/{{name}}/{{name}}.test.tsx', templateFile: 'plop-templates/component.test.hbs' }, ] }) } ``` --- ## 输出模板 ```markdown ## 工程化方案 ### 问题诊断 - 当前瓶颈：…（构建耗时 / CI 耗时 / 包管理问题） ### 方案 - 构建工具：Vite / Webpack 5 + 具体配置 - 包管理：pnpm workspace + Turborepo - CI 优化：缓存策略 + 并行化 + 增量构建 ### 关键配置 - turbo.json pipeline 设计 - CI 缓存 key 策略 - 代码生成工具链 ### 预期收益 - 构建时间：X min → Y min - CI 时间：X min → Y min ```


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)