Appearance
esbuild与vite
元信息
- 目标:理解构建提速的两条路线——esbuild 换语言(Go 原生并行)、Vite 换策略(开发期不打包、按需编译);能说清 gulp→webpack→esbuild→Vite 四代工具各自回应的痛点
- 关键概念:esbuild、Vite、原生并行、按需编译、依赖预构建、HMR
- 关联阶段:cp3
- 常见误区:以为 Vite 开发快是因为打包更快(开发期根本不打包,靠原生 ESM 按需加载);以为 esbuild 是 Vite 的替代品(esbuild 是引擎,Vite 用它做依赖预构建);以为生产构建也被 Vite 省掉了(生产仍用 Rollup 打包,上百个原生 ESM 请求反而慢)
问题:构建为什么慢?
打包工具 webpack 时代的开发体验痛点:每次启动都要先把整个项目打包完,项目越大,等待越久;改一行代码,热更新也要等模块链重新走一遍。根因在于 JavaScript 单线程——打包器的每一个解析、转换、拼接步骤都挤在一条线程上排队。
出路有两条,本篇两个工具各代表一条:
- 换语言:esbuild 用 Go 重写打包器,编译为原生机器码,天然并行
- 换策略:Vite 在开发期干脆不打包,直接利用浏览器的原生 ESM 按需加载
esbuild:用 Go 重写构建
https://esbuild.github.io/ — 用 Go 编写的极快打包/压缩工具。速度优势来自工程选择而非魔法:
- 编译为原生机器码执行,而非解释执行 JS
- 解析、打包、压缩、生成 sourcemap 全部并行化,充分利用多核
- 数据结构为速度量身定制,尽量减少内存分配与遍历次数
- 从头到尾只访存一遍代码,中间结果不落盘
通常比 webpack 等同类工具快 10~100 倍。代价是功能克制:热更新、代码分割的灵活性等留待上层工具补足。因此 esbuild 的常见身份不是你的直接工具,而是别人工具箱里的引擎——Vite 的依赖预构建用的就是它。
bash
esbuild app.js --bundle --outfile=out.js --minify # 一条命令完成打包+压缩Vite:不打包的开发服务器
https://vitejs.cn/(官方 https://vite.dev/)— 由 Vue 作者 Evan You 创建的新一代构建工具。核心洞察:开发期不需要打包,生产期才需要。
- 开发期:启动一个 dev server,浏览器请求哪个模块就实时转换哪个模块(按需编译)。启动几乎是即时的,因为"打包"这一步根本不存在;模块热更新(HMR)只替换改动的那个模块,与项目大小无关
- 依赖预构建:node_modules 里的第三方包(ESM 形态参差)用 esbuild 一次性预打包,之后作为缓存静候——快而不乱
- 生产期:用 Rollup 打包,输出高度优化的静态资源(社区正以 Rust 重写的 Rolldown 替换 Rollup,思路不变:生产必须打包,因为上百个原生 ESM 请求反而更慢)
- 开箱即用的 TypeScript、JSX、CSS 预处理器支持,插件 API 兼容 Rollup 生态
bash
npm create vite@latest my-app # 选 vanilla/javascript,几秒即得一个工程化项目
cd my-app && npm run dev # 即时启动 dev server四代工具一张表
| gulp | webpack | esbuild | Vite | |
|---|---|---|---|---|
| 年代 | 2013 | 2012 | 2020 | 2020 |
| 语言 | JS | JS | Go | JS(引擎用 esbuild/Rollup) |
| 定位 | 任务流自动化 | 一切资源皆模块 | 极速打包/压缩引擎 | 开发服务器 + 构建编排 |
| 开发期启动 | — | 全量打包后才可用 | — | 即时(按需编译) |
| 现状 | 历史地位 | 仍广泛服役 | 作为底层引擎 | 现代项目默认起点 |
一句话谱系:gulp 解决"重复劳动",webpack 解决"依赖打包",esbuild 解决"打包速度",Vite 重新划分"开发不打包、生产才打包"——每次都是对上一代痛点的直接回答。
扩展阅读
- 为什么 esbuild 这么快 https://esbuild.github.io/faq/
- 为什么选 Vite https://cn.vite.dev/guide/why
- vite 实操见打包工具vite.js,动手环节见实训:构建工具