esbuild 配置 #
配置方式概述 #
esbuild 提供三种配置方式:
text
┌─────────────────────────────────────────────────────────────┐
│ esbuild 配置方式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 命令行参数 │
│ └── esbuild src/index.js --bundle --minify │
│ │
│ 2. JavaScript API │
│ └── esbuild.build({ ... }) │
│ │
│ 3. 配置文件 │
│ └── esbuild.config.js / build.js │
│ │
└─────────────────────────────────────────────────────────────┘
入口配置 #
entryPoints - 入口文件 #
指定打包的入口文件:
javascript
const esbuild = require('esbuild');
// 单入口 - 字符串
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
});
// 单入口 - 数组
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
});
// 多入口 - 数组
esbuild.build({
entryPoints: ['src/index.js', 'src/admin.js'],
bundle: true,
outdir: 'dist',
});
// 多入口 - 对象(自定义输出名称)
esbuild.build({
entryPoints: {
main: 'src/index.js',
admin: 'src/admin.js',
vendor: 'src/vendor.js',
},
bundle: true,
outdir: 'dist',
});
stdin - 内联代码 #
直接传入代码字符串:
javascript
const esbuild = require('esbuild');
const result = esbuild.buildSync({
stdin: {
contents: `
import { greet } from './greet.js';
console.log(greet('World'));
`,
resolveDir: __dirname,
sourcefile: 'virtual-entry.js',
loader: 'js',
},
bundle: true,
outfile: 'dist/bundle.js',
});
absWorkingDir - 工作目录 #
指定工作目录:
javascript
esbuild.build({
absWorkingDir: '/path/to/project',
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
});
输出配置 #
outfile 与 outdir #
javascript
// 单文件输出
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
});
// 多文件输出目录
esbuild.build({
entryPoints: ['src/index.js', 'src/admin.js'],
bundle: true,
outdir: 'dist',
});
format - 输出格式 #
javascript
// IIFE - 立即执行函数(浏览器直接使用)
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
format: 'iife',
outfile: 'dist/bundle.js',
});
// 输出: (function() { ... })();
// ESM - ES 模块
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
format: 'esm',
outfile: 'dist/bundle.mjs',
});
// 输出: import { ... } from '...'; export default ...;
// CJS - CommonJS
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
format: 'cjs',
outfile: 'dist/bundle.cjs',
});
// 输出: const ... = require('...'); module.exports = ...;
// UMD - 通用模块定义
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
format: 'umd',
globalName: 'MyLibrary',
outfile: 'dist/bundle.umd.js',
});
// 输出: (function (global, factory) { ... })(this, function() { ... });
globalName - 全局变量名 #
用于 UMD 和 IIFE 格式:
javascript
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
format: 'iife',
globalName: 'MyApp',
outfile: 'dist/bundle.js',
});
// 输出后可通过 window.MyApp 访问
支持嵌套命名:
javascript
esbuild.build({
globalName: 'com.example.myApp',
// 输出: window.com = { example: { myApp: ... } }
});
platform - 目标平台 #
javascript
// 浏览器平台
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
platform: 'browser',
outfile: 'dist/bundle.js',
});
// Node.js 平台
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
platform: 'node',
outfile: 'dist/bundle.js',
});
// 中性平台
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
platform: 'neutral',
outfile: 'dist/bundle.js',
});
平台差异:
| 特性 | browser | node | neutral |
|---|---|---|---|
| 默认格式 | iife | cjs | esm |
| Node.js 内置模块 | 不打包 | 打包 | 不打包 |
| process.env | 替换 | 保留 | 保留 |
| __dirname/__filename | 不定义 | 定义 | 不定义 |
target - 目标环境 #
javascript
// 指定 ES 版本
esbuild.build({
target: 'es2020',
});
// 指定浏览器版本
esbuild.build({
target: ['chrome80', 'firefox78', 'safari14', 'edge80'],
});
// 指定 Node.js 版本
esbuild.build({
platform: 'node',
target: ['node16', 'node18', 'node20'],
});
// 混合指定
esbuild.build({
target: ['es2020', 'chrome80', 'node16'],
});
sourcemap - Source Map #
javascript
// 不生成 Source Map(默认)
esbuild.build({
sourcemap: false,
});
// 生成外部 Source Map 文件
esbuild.build({
sourcemap: true, // 或 'external'
outfile: 'dist/bundle.js',
});
// 生成 bundle.js 和 bundle.js.map
// 内联 Source Map
esbuild.build({
sourcemap: 'inline',
outfile: 'dist/bundle.js',
});
// 内联并返回 Source Map
esbuild.build({
sourcemap: 'linked',
sourcesContent: false, // 不包含源代码
});
banner 与 footer #
在输出文件中添加内容:
javascript
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
banner: {
js: '// Copyright 2024 My Company\n// Licensed under MIT',
css: '/* Copyright 2024 My Company */',
},
footer: {
js: 'console.log("Build time: " + new Date().toISOString());',
css: '/* End of styles */',
},
});
entryNames 与 chunkNames #
自定义输出文件名:
javascript
esbuild.build({
entryPoints: {
main: 'src/index.js',
admin: 'src/admin.js',
},
bundle: true,
outdir: 'dist',
entryNames: '[name]-[hash]',
chunkNames: 'chunks/[name]-[hash]',
});
// 输出:
// dist/main-A1B2C3D4.js
// dist/admin-E5F6G7H8.js
// dist/chunks/vendor-I9J0K1L2.js
占位符说明:
| 占位符 | 说明 |
|---|---|
[name] |
入口名称 |
[hash] |
内容哈希 |
[dir] |
相对目录 |
assetNames #
静态资源命名:
javascript
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
loader: {
'.png': 'file',
'.svg': 'file',
},
assetNames: 'assets/[name]-[hash]',
});
// 图片输出到 dist/assets/ 目录
模块处理配置 #
external - 外部模块 #
排除不打包的模块:
javascript
// 数组形式
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
external: ['lodash', 'react', 'react-dom'],
});
// 函数形式(高级用法)
esbuild.build({
external: (id) => {
// 排除所有 node_modules
if (id.includes('node_modules')) {
return true;
}
// 排除特定前缀
if (id.startsWith('@myorg/')) {
return true;
}
return false;
},
});
packages - 包处理方式 #
javascript
// 排除所有依赖
esbuild.build({
packages: 'external',
bundle: true,
});
// 默认行为(打包所有依赖)
esbuild.build({
packages: 'bundle',
bundle: true,
});
alias - 路径别名 #
javascript
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
alias: {
'@': './src',
'@components': './src/components',
'@utils': './src/utils',
'@hooks': './src/hooks',
'@types': './src/types',
},
});
使用示例:
javascript
// 原来
import { Button } from '../../../components/Button';
import { formatDate } from '../../../utils/date';
// 使用别名后
import { Button } from '@/components/Button';
import { formatDate } from '@utils/date';
mainFields - 主字段 #
指定 package.json 中使用的字段:
javascript
// 默认值(browser 平台)
esbuild.build({
mainFields: ['browser', 'module', 'main'],
});
// Node.js 平台默认
esbuild.build({
platform: 'node',
mainFields: ['main', 'module'],
});
// 自定义
esbuild.build({
mainFields: ['es2015', 'module', 'main'],
});
conditions - 条件导出 #
javascript
esbuild.build({
conditions: ['production', 'browser'],
});
// 对应 package.json 中的条件导出
// {
// "exports": {
// ".": {
// "production": "./dist/prod.js",
// "development": "./dist/dev.js",
// "default": "./dist/index.js"
// }
// }
// }
resolveExtensions - 解析扩展名 #
javascript
esbuild.build({
resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.json', '.css'],
});
优化配置 #
minify - 压缩 #
javascript
// 完整压缩
esbuild.build({
minify: true,
});
// 分别控制
esbuild.build({
minifyWhitespace: true, // 移除空白
minifyIdentifiers: true, // 缩短变量名
minifySyntax: true, // 优化语法
});
// 只压缩空白(保留可读性)
esbuild.build({
minifyWhitespace: true,
minifyIdentifiers: false,
minifySyntax: false,
});
drop - 移除代码 #
javascript
// 移除 console
esbuild.build({
drop: ['console'],
});
// 移除 debugger
esbuild.build({
drop: ['debugger'],
});
// 同时移除
esbuild.build({
drop: ['console', 'debugger'],
});
pure - 纯函数标记 #
javascript
esbuild.build({
pure: ['console.log', 'console.info', 'console.debug'],
});
// 被标记的函数如果结果未使用,将被移除
// console.log('debug info') 会被移除
ignoreAnnotations - 忽略注释 #
javascript
esbuild.build({
ignoreAnnotations: true,
});
// 忽略 /* @__PURE__ */ 和 /* @__NO_SIDE_EFFECTS__ */ 注释
legalComments - 法律注释 #
javascript
// 内联注释(默认)
esbuild.build({
legalComments: 'inline',
});
// 提取到外部文件
esbuild.build({
legalComments: 'external',
outfile: 'dist/bundle.js',
});
// 生成 bundle.js.LEGAL.txt
// 返回注释内容
esbuild.build({
legalComments: 'linked',
});
// 保留原始位置
esbuild.build({
legalComments: 'eof',
});
// 移除所有注释
esbuild.build({
legalComments: 'none',
});
treeShaking - Tree Shaking #
javascript
// 默认启用
esbuild.build({
treeShaking: true,
});
// 禁用(保留所有代码)
esbuild.build({
treeShaking: false,
});
// 忽略副作用注释
esbuild.build({
treeShaking: 'ignore-annotations',
});
定义和替换 #
define - 全局定义 #
javascript
esbuild.build({
define: {
'process.env.NODE_ENV': '"production"',
'process.env.VERSION': '"1.0.0"',
'process.env.DEBUG': 'false',
'global': 'globalThis',
},
});
使用表达式:
javascript
esbuild.build({
define: {
'process.env.API_URL': JSON.stringify('https://api.example.com'),
'process.env.BUILD_TIME': JSON.stringify(new Date().toISOString()),
},
});
inject - 注入文件 #
javascript
// inject.js
export const process = { env: { NODE_ENV: 'production' } };
// 配置
esbuild.build({
inject: ['./inject.js'],
define: {
// 如果需要替换全局 process
'process': 'process',
},
});
常见用途 - 注入 Node.js polyfill:
javascript
// node-polyfills.js
export const process = {
env: {},
version: 'v18.0.0',
};
export const Buffer = class Buffer {
static from(str) { return str; }
};
export const __dirname = '/';
export const __filename = '/index.js';
Loader 配置 #
loader - 文件加载器 #
javascript
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
loader: {
'.js': 'js',
'.jsx': 'jsx',
'.ts': 'ts',
'.tsx': 'tsx',
'.css': 'css',
'.module.css': 'local-css',
'.json': 'json',
'.txt': 'text',
'.png': 'dataurl',
'.jpg': 'file',
'.svg': 'file',
'.woff': 'file',
'.woff2': 'file',
},
});
各加载器详解 #
JavaScript 加载器 #
javascript
loader: {
'.js': 'js', // 标准 JavaScript
'.jsx': 'jsx', // JavaScript + JSX
'.ts': 'ts', // TypeScript
'.tsx': 'tsx', // TypeScript + JSX
'.mjs': 'js', // ES 模块
'.cjs': 'js', // CommonJS
}
CSS 加载器 #
javascript
loader: {
'.css': 'css', // 标准 CSS
'.local.css': 'local-css', // CSS Modules
}
数据加载器 #
javascript
loader: {
'.json': 'json', // JSON 对象
'.txt': 'text', // 文本字符串
'.binary': 'binary', // 二进制数据
}
文件加载器 #
javascript
loader: {
'.png': 'dataurl', // Base64 内联
'.jpg': 'file', // 复制文件
'.svg': 'file', // 复制文件
'.woff': 'file', // 复制文件
'.pdf': 'copy', // 复制到输出目录
}
JSX 配置 #
jsx - JSX 转换模式 #
javascript
// 经典模式(默认)
esbuild.build({
jsx: 'transform',
jsxFactory: 'React.createElement',
jsxFragment: 'React.Fragment',
});
// 自动模式(React 17+)
esbuild.build({
jsx: 'automatic',
jsxImportSource: 'react',
});
// 保留模式
esbuild.build({
jsx: 'preserve',
});
jsxFactory 与 jsxFragment #
javascript
// Preact
esbuild.build({
jsxFactory: 'h',
jsxFragment: 'Fragment',
});
// 自定义
esbuild.build({
jsxFactory: 'createElement',
jsxFragment: 'Fragment',
});
jsxImportSource #
javascript
// React
esbuild.build({
jsx: 'automatic',
jsxImportSource: 'react',
});
// Emotion
esbuild.build({
jsx: 'automatic',
jsxImportSource: '@emotion/react',
});
// 自定义路径
esbuild.build({
jsx: 'automatic',
jsxImportSource: '@/jsx-runtime',
});
构建元数据 #
metafile - 元数据输出 #
javascript
const result = await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
metafile: true,
});
console.log(result.metafile);
// 分析元数据
const analysis = await esbuild.analyzeMetafile(result.metafile);
console.log(analysis);
输出到文件:
bash
esbuild src/index.js --bundle --metafile=meta.json --outfile=dist/bundle.js
分析构建结果 #
javascript
const esbuild = require('esbuild');
const fs = require('fs');
async function analyze() {
const result = await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
metafile: true,
outfile: 'dist/bundle.js',
});
const analysis = await esbuild.analyzeMetafile(result.metafile, {
verbose: true,
});
console.log(analysis);
}
analyze();
输出示例:
text
dist/bundle.js 125.2kb
├ src/index.js 45.2kb
├ node_modules/lodash/index.js 35.1kb
├ src/utils.js 25.0kb
└ src/components.js 19.9kb
增量构建 #
context API #
javascript
const esbuild = require('esbuild');
async function setup() {
const ctx = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
});
// 手动重新构建
await ctx.rebuild();
// 启用监听
await ctx.watch();
// 启动服务
const { host, port } = await ctx.serve({
servedir: 'dist',
});
console.log(`Server: http://${host}:${port}`);
}
setup();
rebuild - 手动重建 #
javascript
const ctx = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
});
// 首次构建
await ctx.rebuild();
// 文件变化后再次构建
await ctx.rebuild();
// 清理
await ctx.dispose();
watch - 监听模式 #
javascript
const ctx = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
});
await ctx.watch();
// 停止监听
// await ctx.dispose();
serve - 开发服务器 #
javascript
const ctx = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
});
const server = await ctx.serve({
port: 3000,
host: 'localhost',
servedir: 'dist',
onRequest: (args) => {
console.log(`${args.method} ${args.path} - ${args.status}`);
},
});
console.log(`Server running at http://${server.host}:${server.port}`);
完整配置示例 #
库开发配置 #
javascript
const esbuild = require('esbuild');
const sharedConfig = {
entryPoints: ['src/index.ts'],
bundle: true,
sourcemap: true,
external: ['react', 'react-dom'],
loader: {
'.ts': 'ts',
'.tsx': 'tsx',
},
};
async function build() {
// ESM
await esbuild.build({
...sharedConfig,
format: 'esm',
outfile: 'dist/index.esm.js',
});
// CommonJS
await esbuild.build({
...sharedConfig,
format: 'cjs',
outfile: 'dist/index.cjs.js',
});
// UMD
await esbuild.build({
...sharedConfig,
format: 'umd',
globalName: 'MyLib',
outfile: 'dist/index.umd.js',
});
console.log('Build complete!');
}
build();
应用开发配置 #
javascript
const esbuild = require('esbuild');
const isDev = process.env.NODE_ENV !== 'production';
async function build() {
const ctx = await esbuild.context({
entryPoints: ['src/index.tsx'],
bundle: true,
outdir: 'dist',
format: 'esm',
platform: 'browser',
target: ['es2020', 'chrome80', 'firefox78', 'safari14'],
sourcemap: isDev,
minify: !isDev,
define: {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
},
loader: {
'.tsx': 'tsx',
'.ts': 'ts',
'.css': 'css',
'.png': 'dataurl',
'.svg': 'file',
},
alias: {
'@': './src',
},
});
if (isDev) {
await ctx.watch();
const { host, port } = await ctx.serve({
servedir: 'dist',
port: 3000,
});
console.log(`Dev server: http://${host}:${port}`);
} else {
await ctx.rebuild();
await ctx.dispose();
console.log('Build complete!');
}
}
build().catch(() => process.exit(1));
Node.js 应用配置 #
javascript
const esbuild = require('esbuild');
esbuild.build({
entryPoints: ['src/server.ts'],
bundle: true,
platform: 'node',
target: 'node18',
format: 'cjs',
outfile: 'dist/server.js',
external: [
'express',
'mongoose',
'redis',
// 其他生产依赖
],
loader: {
'.ts': 'ts',
},
minify: true,
sourcemap: true,
}).then(() => {
console.log('Server build complete!');
});
下一步 #
现在你已经掌握了 esbuild 的详细配置,接下来学习 插件系统 扩展 esbuild 的能力!
最后更新:2026-03-28