2025.09.01
极致性能:使用 ESBuild 极速构建
🎯 为什么选择 ESBuild?
核心优势 ⬇️
| 特性 | 描述 | 速度对比 |
|---|---|---|
| 🚀 闪电般的速度 | 使用 Go 语言编写,实现了数倍于传统工具链的性能提升。 | 比 Webpack 快 10–100 倍 |
| 🛠️ 极简配置 | 开箱即用,强大的默认配置让复杂构建变得简单。 | 接近零配置 |
| 📦 灵活的输出 | 原生支持主流模块格式,适应各种使用环境。 | 支持 ESM CJS IIFE |
| 🧠 TypeScript 原生支持 | 无需 Babel 或额外的 tsc 预编译步骤。 | 直接解析 ts 文件 |
| 🔄 实时反馈 | 内置文件监听 (watch),提供即时的重编译反馈。 | 优秀的开发体验 |
🚀 快速上手
步骤 1️⃣:配置开发脚本
在 package.json 中添加开发脚本:
{
"scripts": {
"dev": "node scripts/dev.js reactivity --format esm"
}
}
运行效果:
- 🚀 启动开发模式
- 👀 监听文件变更并实时构建
- 📦 以 ESM 格式输出到
dist目录
步骤 2️⃣:创建构建脚本
新建 scripts 目录,并在里面创建 dev.js 文件:
/**
* 🔥 ESBuild Monorepo 开发构建脚本
*
* 功能:
* - 📁 支持任意 packages/* 子包作为构建目标。
* - 🎯 灵活控制输出格式(esm/cjs/iife)。
* - 👀 启用实时 watch 模式。
* - 🗺️ 自动生成 Source Map。
*
* 示例用法:
* pnpm dev reactivity --format esm
* pnpm dev vue -f cjs
*/
import { createRequire } from 'node:module'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { parseArgs } from 'node:util'
import esbuild from 'esbuild'
// 🔧 工具函数:解决 ESM 环境下的兼容性问题
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const require = createRequire(import.meta.url)
// 📝 1. 解析命令行参数
const {
values: { format },
positionals
} = parseArgs({
allowPositionals: true,
options: {
format: { type: 'string', short: 'f', default: 'esm' } // 默认输出 ESM 格式
}
})
// 🎯 2. 确定构建目标和路径
const target = positionals.length ? positionals[0] : 'vue' // 默认构建 vue 包
const entry = resolve(__dirname, `../packages/${target}/src/index.ts`)
const outfile = resolve(__dirname, `../packages/${target}/dist/${target}.${format}.js`)
// 📦 3. 读取包配置 (用于获取 globalName)
const pkg = require(`../packages/${target}/package.json`)
// 🚀 4. 启动 ESBuild 构建上下文并监听
esbuild
.context({
entryPoints: [entry], // 📥 入口文件
outfile, // 📤 输出路径
format: format === 'iife' ? 'iife' : format, // 🎨 确保 iife 格式正确
platform: format === 'cjs' ? 'node' : 'browser', // 🌐 目标运行环境
sourcemap: true, // 🗺️ 启用 Source Map
bundle: true, // 📦 启用打包 (将依赖内联)
globalName: pkg.buildOptions?.name // 🏷️ 配置 IIFE 模式下的全局变量名
})
.then((ctx) => {
console.log(`\n👀 Watching for changes in @vue/${target}...`)
return ctx.watch() // 👀 启动文件监听
})
📋 过检参数
| 参数 | 说明 | 可选值 | 默认值 |
|---|---|---|---|
| 位置参数 | 指定要构建的包名 | reactivity, vue, shared | vue |
--format / -f | 输出格式 | esm, cjs, iife | esm |
🎨 输出格式对比
| 格式 | 用途 | 特点 |
|---|---|---|
ESM | 现代浏览器、Node.js | 原生模块系统,Tree-shaking 友好 |
CJS | Node.js 环境 | CommonJS 格式,向后兼容 |
IIFE | 浏览器直接引入 | 立即执行函数,全局变量 |
🚀 使用示例
# 1. 开发 reactivity 包,以 ESM 格式输出
pnpm dev reactivity --format esm
# 2. 构建 vue 包,用于 Node.js 服务端渲染 (CommonJS)
pnpm dev vue -f cjs
# 3. 构建 shared 包,用于浏览器直接引入 (IIFE)
pnpm dev shared --format iife
📁 输出结构
构建完成后,文件会输出到对应包的 dist 目录:
packages/
├── reactivity/
│ └── dist/
│ ├── reactivity.esm.js # ESM 格式
│ ├── reactivity.cjs.js # CommonJS 格式
│ └── reactivity.iife.js # IIFE 格式
└── vue/
└── dist/
├── vue.esm.js
├── vue.cjs.js
└── vue.iife.js