Agent Developer Roadmap
构建工具

构建工具决策表:先固定问题,再比较实现

核验日期:2026-07-10。各工具使用 examples/build-tools 中的同一份输入;版本以示例 package.json 为准。任何性能结论都必须重新记录机器、版本、缓存状态、样本和产物契约。

需要掌握的问题

主题必须回答的问题原理与边界高频错误证据与来源
三类问题当前要解决语法转换、应用打包还是库发布?转换器处理单模块;应用工具还要管理开发服务器、模块图和浏览器入口;库工具优先保证 exports、external 与多格式消费把八个工具放进一张“速度榜”共享示例把 transformer 与 bundler 分组;esbuild Transform API
职责与宿主谁拥有配置、resolve、transform、chunk、HTML 和运行时?Babel/SWC 常嵌入宿主;Vite 是工作流;webpack/Rspack、Rollup/Rolldown、esbuild Build 是打包底座为单段性能替换整条工具链八篇文章与本页职责对照
性能条件冷构建、热更新、增量构建还是 CI 吞吐超标?不同阶段复用的状态不同;原生实现、JS 插件跨边界、I/O、Source Map 和 minify 都会改变结果用四个模块的小样例宣布普遍排名示例 benchmark 输出机器、版本、samples 和 median;esbuild FAQ
可靠性如何证明解析、图、分块、Source Map 和浏览器加载都正确?命令退出 0 只证明流程未抛错;结构化 metadata 与浏览器验收才证明产物契约只比耗时或文件字节数artifacts.test.mjs 验证 HTML、async chunk、metadata、map 和路径
缓存与 HMR哪一层缓存什么,失效由谁负责?转换缓存、模块图缓存、持久化缓存与 HMR runtime 是不同状态机把 watch、live reload、HMR 混为一谈webpack cacheVite HMR API
插件生态插件 API 兼容是否等于行为完全一致?hook 名称可以兼容,调用时机、上下文、内建模块与输出语义仍可能不同不跑真实插件 fixture 就迁移引擎Rspack plugin compatibilityRolldown Plugin API
产物与发布应用和库分别要交付什么?应用交付 HTML、hash assets、runtime/manifest;库交付 exports、类型、external 策略和消费端兼容用“能生成一个 JS”替代发布验收Rollup configuration、共享 artifact tests
迁移成本能否按阶段替换并回滚?配置相似只是表面;自定义 Loader/Plugin、HMR、SSR、Module Federation 和发布脚本决定成本一次性替换开发、构建、测试与部署webpack→Rspack、Rollup→Rolldown 分层迁移表
安全边界构建插件和 Source Map 接触哪些秘密?配置与插件以 Node 权限执行;公开 map、define/env 和远程插件可能泄露源码或凭据给不可信 PR 构建注入生产 secretVite env boundary、各文章安全章节

这是一篇工具选型文章,编程语言的数据结构、浏览器持久化、UI 可访问性不属于它的直接职责;但浏览器加载、运行时 chunk、Source Map 暴露和插件代码执行会影响构建结果,因此必须纳入验收与信任边界。

先固定语法转换、应用打包、库发布三类问题

“构建工具”至少包含三种不同采购问题。先选问题,再选候选;否则会把 Babel 的 AST 插件能力、Vite 的开发体验和 Rollup 的库发布能力当成同一维指标。

问题输入必要输出不属于最低职责首选候选集
语法转换单个 JS/TS/JSX 字符串或文件目标 JS、诊断、Source Map完整依赖图、CSS、HTML、类型证明Babel、SWC、esbuild Transform
应用打包HTML/JS entry、资源、依赖与环境配置initial/async chunks、CSS/assets、HTML 或 manifest、加载 runtime业务运行时正确性、后端授权Vite、webpack、Rspack、esbuild Build;底层 Rolldown
库发布一个或多个公共入口、peer 依赖、类型声明ESM/CJS 等约定格式、exports 对齐、map、external 保留完整框架 dev server、应用 HTMLRollup、Rolldown;受限场景用 esbuild/Vite library mode

一家公司可以同时使用三类工具:例如 Babel 做遗留语义插件,Vite 管应用开发与生产构建,Rollup 管独立库发布。这不是重复,而是职责组合;真正的重复是多个阶段都在无意中转同一语法、重复压缩或各自解释 targets。

八个工具的职责地图

工具核心职责配置与插件入口缓存/HMR典型产物主要固定成本
Babelparser → AST traverse/transform → generator;按 targets 降级语法preset、plugin、visitor、babel.config.*自身常由宿主缓存;无应用 HMR runtime逐文件 JS 与 Source Map插件顺序、配置发现、polyfill/类型边界
SWCRust parser/transform/codegen;TS/JSX 与兼容转换.swcrc、JS API、Wasm plugin、宿主 Loader宿主决定增量与 HMR逐文件 JS 与 Source Mapnative binary、Wasm ABI、宿主配置映射
esbuildTransform API 做隔离转换;Build API resolve、link、打包JS/Go API、CLI、onResolve/onLoadcontext 支持 rebuild/watch/serve;live reload 不等于框架 HMRJS/CSS chunks、map、metafile;HTML 需自建/插件插件阶段较少,生态与高级应用策略需补齐
ViteHTML-first 开发服务器、按请求转换、HMR、生产构建工作流Vite/Rollup-compatible plugin、Environment APIdev module graph、依赖预构建、HMR runtimeHTML、hash assets、.vite/manifest.jsondev/prod 双路径、框架插件与部署 base
webpack通用应用模块图、Loader/Plugin 生命周期、chunk/runtimeLoader、Tapable Plugin、Compiler/Compilationmemory/filesystem cache、watch、成熟 HMRHTML、JS/CSS assets、runtime、stats配置面广、历史兼容、自定义扩展维护
Rspackwebpack 兼容的 Rust 应用 bundlerwebpack-like config、Loader、兼容 Plugin、built-insincremental、persistent cache、HMR、lazy compilation与 webpack 类似的 assets/runtime/stats兼容组合、native 包、插件跨 JS/Rust 边界
Rollup静态 ESM 图、Tree Shaking、库格式与输出钩子resolveId/load/transform、输出 hookswatch 复用 bundle cache;不提供完整框架 HMRESM/CJS/UMD chunks、assets;HTML/manifest 由插件生成external、exports、side effects、多输出设计
RolldownRust + Oxc 的 Rollup-compatible bundler,内建更多转换/分析Rollup-compatible hooks、hook filters、built-inswatch API;独立使用不等于 Vite HMRchunks/assets;HTML/manifest 要显式配置兼容差异、native/Wasm、快速演进期回归

“插件生态大”也不能单独决策。要区分可安装数量、目标插件是否兼容、维护活跃度、hook 语义、插件是否进入热路径,以及团队是否拥有插件源码。一个只依赖官方框架插件的新应用,与拥有二十个自定义 webpack Plugin 的存量平台,迁移成本完全不同。

语法转换:Babel、SWC 与 esbuild Transform

维度BabelSWCesbuild Transform
职责深度支持深度 AST visitor/preset 定制,适合 codemod、提案与遗留语义插件常见 TS/JSX/React 与 targets 转换,适合作为宿主的高吞吐编译段内存字符串的快速常见转换、minify 与 loader
性能条件JS 插件数、AST 遍历次数、helper/map 会影响耗时native 调用、文件规模、Wasm 插件跨边界影响耗时单次进程启动与批量 API 的差异很大
可靠性生态成熟、可观测配置强;插件顺序可能改变语义内建路径减少 JS 插件差异;native/Wasm 版本要锁定API 面小、默认统一;复杂插件需求可能被迫在外层补胶水
使用难度低门槛 preset,高阶 visitor/配置发现难常规配置短,宿主与 Babel 选项映射需验证Transform API 最小;超出其职责后要切 Build 或宿主
维护成本多插件升级与 Babel major 迁移成本核心配置少,但 binary/ABI 与平台组合有成本配置少;自研缺失 hook 会把成本转移到外围脚本
适用规模规模不是关键;语义定制复杂度才是关键大量模块的通用转换段编辑器、测试器、文档工具中的隔离转换或轻量宿主
迁移成本自定义 Babel plugin 越多越高从 Babel 迁移要逐插件确认语义,不只对比语法能否解析只覆盖 Transform 的项目低;依赖 Babel visitor 的项目高

选择顺序:先列出必须保留的语义插件、decorator/class fields 假设、targets、module format、JSX runtime、Source Map 与类型检查;再用真实源码 fixture 比较输出。若只需删除 TypeScript 类型并保留 ESM,三者都可能完成;若要自定义 AST 分析或尚无等价实现的 Babel plugin,转换耗时不是唯一约束。

共享示例故意证明边界,而不是证明谁更强:Babel 8.0.1 和 SWC 1.15.43 都把四个 .ts 文件转成四个 .js 与 map,保留 ESM,不生成 CSS、HTML 或 bundle。benchmark 中的 esbuild Transform 也只转换内存中的 TS;它不能与六个完整 bundler 的总耗时直接排名。

应用打包:Vite、新旧 webpack/Rspack 与嵌入式 esbuild

新应用先比较工作流,不只比较 bundler

约束Vitewebpack 5Rspack 2esbuild Build独立 Rolldown
开箱开发服务器/HMR强,HTML-first、框架插件成熟强,dev-server 与 HMR 成熟强,面向 webpack 工作流兼容serve/watch 可用;框架 HMR 需上层watch 可用;通常由 Vite 提供应用工作流
复杂资源与历史插件依赖 Vite/Rollup 插件与框架集成在这组候选中 Loader/Plugin 的历史覆盖较广常见 webpack 面兼容,长尾要查兼容说明核心 loader 强,复杂插件点较少Rollup 插件兼容度高,仍需检查差异
持久化/增量dev module graph 与依赖预构建;由框架/插件共同影响filesystem cache、snapshot、watchincremental、persistent cache、lazy compilationcontext/rebuild/watchwatch cache;完整 dev 缓存策略由宿主补齐
大型存量迁移要重画配置、HMR 和插件边界保持现状风险最低但性能改造需证据配置相似,适合分层验证迁移通常需要重写插件与 HTML/runtime 工作流若原系统是 Rollup/Vite 更自然
应用产物HTML、assets、manifestHTML、assets、runtime、statsHTML、assets、runtime、statschunks/assets、metafile;示例脚本生成 HTMLchunks/assets;示例插件生成 HTML/manifest

Vite 是上层开发与构建产品,Rolldown 是 Vite 8 当前的生产打包底座;两者不能用“同一个 Rust 引擎”画等号。Vite 还拥有 HTML 入口、dev module graph、依赖优化、HMR、环境与框架插件。独立 Rolldown 适合需要底层控制或构建工具作者,不是自动替代 Vite 配置。

webpack 还是 Rspack:先做兼容资产清点

webpack 5 与 Rspack 2 的选择通常发生在存量应用。先导出下列清单:

  1. module.rules 中每个 Loader,是否使用 pitch、异步 callback、额外依赖或自定义 metadata。
  2. 每个 Plugin 使用哪些 Compiler/Compilation/Tapable hooks,是否操作 webpack 内部对象。
  3. dev-server、HMR accept/dispose、Module Federation 与 SSR 的运行时契约。
  4. filesystem cache 的 build dependencies、snapshot、跨分支复用策略。
  5. stats、bundle analyzer、部署 manifest、publicPath 和 CDN 发布脚本。

Rspack 官方 webpack 迁移指南明确要求 filesystem cache 从 webpack 的 type: 'filesystem' 映射为 type: 'persistent',字段结构也不同;配置相似不代表可复制缓存对象。迁移应让 webpack 与 Rspack 在同一 commit 双构建,比较 artifact、stats、浏览器测试和性能样本,再逐包切 CI 与本地开发。若关键插件处于部分兼容或不兼容状态,应对照官方 Plugin compatibility 表选择替代插件或保留 webpack,而不是绕过内部 API。

esbuild 最适合被嵌入时

esbuild Build API 在共享示例中能生成 JS/CSS、动态 chunk、Source Map 与 metafile.json,外围配置再据 metadata 写 index.html。这说明它适合作为平台、CLI、测试器或自研框架中的嵌入式引擎:宿主明确拥有 HTML、HMR、缓存、部署和框架语义。

如果团队只想“少写配置”却没有意愿维护宿主层,直接采用 Vite 或框架官方构建方案通常维护成本更低。esbuild 的 API 简洁不会自动消除 HTML 注入、CSS 顺序、legacy browser、错误 overlay、HMR 边界和部署 manifest 等应用职责。

库发布:Rollup、Rolldown 与替代路径

维度Rollup 4Rolldown 1esbuildVite library mode
主要优势成熟 ESM 图、输出格式、Tree Shaking 与插件钩子Rollup-compatible API、Rust/Oxc 内建能力、面向 Vite 演进API 简洁、常见格式与转换吞吐已在 Vite 项目中,复用 alias/框架插件与配置
可靠性条件正确 externalmoduleSideEffects、map 和消费 fixture除同项外,还要验证 hook 调用差异和兼容表检查 CJS/ESM interop、插件缺口与产物约定检查库模式默认值、CSS 与框架插件行为
插件生态Rollup 官方/社区生态成熟可复用多数 Rollup 插件,但不是逐字节等价onResolve/onLoad 模型不同Vite/Rollup-compatible 插件,dev hook 与 build hook 有差异
多输出与 exports强,适合显式设计多入口、多格式API 相近;多 output 与 hook 状态要回归可做,但复杂发布常需脚本组合可做,适合应用仓中的中小库
迁移成本现有 Rollup 项目最低先兼容扫描、双构建、消费测试从 Rollup 插件体系迁移较高从 Vite 应用抽库较低,独立发布治理仍需补齐

库构建的完成条件不是 dist/index.js 存在。至少要检查:

  • package.json#exports 的每个 public subpath 都有文件,未声明的内部文件不能被误依赖。
  • peerDependenciesexternal 一致,React/Vue 等单例运行时不会被重复打包。
  • ESM/CJS 消费 fixture、Node 与目标 bundler 都能加载对应条件。
  • .d.ts 与 JS 入口、Source Map、CSS/assets 的发布清单一致。
  • dynamic import、top-level await、side effects 与 tree shaking 在消费者中保持语义。

Rollup→Rolldown 迁移的低风险边界是保留 input/output 约定,先逐个插件验证 resolveId/load/transform/generateBundle,再比较产物和消费者;Rolldown Plugin API 的差异说明列出了多 output、watch 与 hook 顺序的行为差异。不要因为 API compatible 就跳过 fixture。

性能比较必须写清条件

性能不是一个数。至少拆成以下指标:

指标固定条件反映什么不能推出什么
冷启动/冷构建清理工具缓存与 OS 缓存策略、固定依赖安装CI 首次构建和新开发机体验热更新速度、长期产物质量
热构建/增量先完成一次构建,固定修改同一模块图复用、缓存失效与局部重算全量构建吞吐
HMR 延迟固定浏览器、页面路径、更新模块和 accept 边界从保存到浏览器应用更新的链路生产构建速度
峰值内存/CPU固定并发、Source Map、minify 和 workerCI 容量与开发机争用用户运行时性能
产物字节/请求相同 target、minifier、split 策略、压缩算法网络与缓存候选成本浏览器解析/执行一定更快
正确性通过率相同 artifact 与浏览器测试优化是否保持语义所有业务路径都正确

共享命令只提供测量方法:

pnpm --silent --filter @roadmap/build-tools-slice benchmark -- --warmup=1 --iterations=5

预期输出是一份 JSON:包含 Node、pnpm、工具版本、CPU、内存、每次 samplesMs、median/min/max 和 outputBytes;transformers 与 bundlers 分组。当前 benchmark 的 target、minify、Source Map 与产物职责并未完全统一,因此 outputBytes 不能跨工具横向比较,也不能据此给工具排产物体积名次。它只有四个源码模块,无法代表十万模块 monorepo、复杂框架 HMR 或 CI 远程缓存。真实横评应先统一 target、minify、Source Map、entry、split 和 side-effect 契约,再使用代表性入口重复至少三轮并保存原始 samples,而不是只抄 median。

可靠性、学习难度与维护成本要一起算

成本来源早期看起来长期故障可审查证据
内建能力配置更短默认升级可能改变语义锁版本、升级 diff、产物 fixture
社区插件很快补齐功能维护停滞、供应链、hook 不兼容owner/Release、最小插件测试、依赖审计
自研插件完全贴合业务只有少数人懂内部生命周期设计说明、单元/集成 fixture、退出方案
多段编译每段都能解决局部问题targets、module、map、minify 重复或冲突打印最终 config、记录每阶段输入输出
缓存第二次构建很快错误命中、跨平台/分支污染缓存 key、miss reason、冷/热双测
兼容层配置几乎不改长尾插件或 runtime 行为偏差官方兼容组合、双构建、浏览器回归

学习难度不是配置文件行数。webpack 的 Loader/Plugin 和 chunk runtime 较显式,Vite 默认更短但需要理解 dev/prod 双路径,Rollup/Rolldown 要理解 ESM、external 与输出 hooks,Babel 要理解 AST 和插件顺序。维护成本则由团队必须解释的失败模式决定:如果没人能解释 HMR dispose、cache invalidation 或 exports,短配置也会变成长事故。

迁移要保留可回滚的证据链

迁移低风险起点高风险边界退出条件
Babel→SWC/esbuild只删 TS 类型、常规 JSX、保留 ESM自定义 Babel visitor、proposal、宏、instrumentation所有转换 fixture、map、targets 与类型检查通过
webpack→Rspack内建资源、常见 Loader、基础 chunks内部 Compiler/Compilation API、长尾 Plugin、Federation runtime双构建 artifact/browser、缓存和性能预算通过
Rollup→Rolldown标准 hooks、ESM、单 outputhook 顺序状态、多 output、边缘 CJS、复杂 CSS/HTML 插件消费 fixture 与产物语义通过,不要求字节相同
自研 esbuild→Vite保留业务源码与 public assetHTML、env、HMR、SSR、manifest 约定开发与生产双路径均通过
Vite/Rollup 引擎升级官方插件和显式配置依赖未声明内部实现、脆弱产物快照ecosystem/业务回归与部署静态预览通过

常见错误与修正证据

表现根因先观察修正
Babel/SWC 命令成功但页面不能打开只完成语法转换dist 是否有 HTML、CSS、依赖被解析交给 bundler/dev server,不给 transformer 虚构职责
dev 很快,production 白屏Vite dev 与 build 路径、插件 hooks 或 base 不一致vite build 后静态预览、Network、manifest同时验收 dev 和 production artifact
Rspack 构建成功但行为不同webpack Plugin/Loader 或 cache 字段只部分兼容兼容组合、stats diff、插件 fixture换 built-in/替代插件,或保留 webpack
库在本仓能 import,发布后失败exports、文件清单、类型或 external 错位npm pack 内容与独立消费者对齐入口并跑 ESM/CJS/目标 bundler fixture
Tree Shaking 删除 CSS/注册逻辑错误声明 sideEffects: false/moduleSideEffects: false搜索可观察 marker、浏览器行为明确保留副作用路径并写回归测试
async chunk 线上 404publicPath/base、旧 HTML 或 CDN 缓存不一致HTML、manifest/stats、Network URL 和响应头HTML 短缓存,hash assets 长缓存,原子发布
HMR 后监听器翻倍accept/dispose 边界没有清理副作用控制台计数、事件监听、timer在 dispose 清理;不能安全接受时 full reload
Source Map 指向生成代码或泄露本机路径中间插件丢 map,或公开发布 external map解析 .map.sources、搜索工作区绝对路径传递上游 map;使用 hidden map/受控上传
新工具 benchmark 更快但 CI 更慢本地样例、缓存或进程模型不一致原始 samples、CPU/内存、安装与启动时间在真实 CI 以相同契约重测

一份可审查的选择记录

不要直接给工具打永久总分。为当前项目填写权重与证据:

约束权重候选证据通过线
语义/产物可靠性5artifact、浏览器或消费者测试100% 关键路径通过
关键插件兼容5每个必须插件的 fixture 与官方兼容说明无未解释的不兼容
冷/热性能3真实仓库原始样本和 CI 资源达到团队 SLO
开发/HMR3固定编辑场景、状态保留、错误恢复无重复副作用或长期 full reload
维护与升级4owner、版本策略、自研代码量、回滚步骤团队可值班和升级
迁移成本4双轨周期、配置/插件/部署改动能分阶段回滚

最终记录应写成“在 Node、浏览器、模块数、插件集、Source Map/minify 和缓存条件 X 下,候选 A 满足正确性并达到预算 Y,因此用于场景 Z;若插件 P 或运行时 R 不通过则保留候选 B”,而不是“工具 A 比工具 B 快”。

官方资料入口

在 GitHub 上编辑此页

本页目录