ESbuild 是一款基于 Golang 开发的打包工具,相比传统的 webpack、rollup 等主打性能优势,在构建速度上可以快 10~100 倍。

安装
bash
npm i esbuild打包
esbuild 包含了两个打包方法,同步打包buildSync和异步打包build。
接受一个打包对象 option。
- entryPoints:入口文件,Array/String
- outfile:打包输出文件,Array/String
- bundle:将依赖项内联到文件本身,并且是递归的,默认不会捆绑依赖。Boolean ::: tip 如果 bundle=true,会打包成一个 iife 立即执行函数 :::
- loader:对文件类型使用对应的 loader 解释文件。 ::: tip 类型包含有 js、ts、jsx、json、css、text、binary、base64、data url、external file :::
- plugin:插件,Array
示例
text
require('esbuild').buildSync({
entryPoints: ['main.js'],
outfile: 'out.js',
bundle: true,
loader: {'.js': 'jsx', '.json': 'js'},
plugin:[]
})plugin
- 一个 esbuild 插件是一个包含 name 属性和 setup 函数的对象
- 他们以数组的形式传递给构建 API 调用,
setup函数接收一个build参数,函数在每次BUILD API调用时都会运行一次。
命名空间 name
- 每个模块都有一个关联的命名空间。默认情况下,esbuild 在 file 命名空间中云星,该命名空间对应文件系统上的文件类型
- esbuild 也可以处理在文件系统上没有对应位置的“虚拟”模块
- 插件可用于创建虚拟模块。虚拟模块通常使用命名空间而不是 file 将他们与文件系统模块区分开来,通常命名空间特定于创建他们的插件
setup 函数
- setup 函数接受一个 build 参数,build 指的就是 esbuild,在 esbuild 打包过程中会调用每一个插件里 setup 中的回调函数,onResolve,onLoad
onResolve 回调
- 使用添加的回调 onResolve 将在 esbuild 构建的每个模块中的每个导入路径上运行
- 回调函数可以自定义 esbuild 如何解析路径。例如可以拦截导入路径并将他们重定向到其他地方,也可以将路径标记为外部:external:true
- 回调函数中如果返回了内容,那么不会再走后续插件中的 onResolve 回调
js
// 最终生成的onResolve回调[p1.onResolve1, p1.onResolve2, p2.onResolve1, p2.onResolve2]
// plugin1
const plugin1 = {
name: "p1",
setup(build) {
build.onResolve({ filter: /.js$/ }, () => {
console.log("p1 resolve1");
return {
path: "C:/Users/xxx/xxx/xxx/xxx.js",
};
});
build.onResolve({ filter: /.js$/ }, () => {
console.log("p1 resolve2");
});
},
};
// plugin2
const plugin2 = {
name: "p2",
setup(build) {
build.onResolve({ filter: /.js$/ }, () => {
console.log("p2 resolve1");
});
build.onResolve({ filter: /.js$/ }, () => {
console.log("p2 resolve2");
});
},
};
require("esbuild").build({
entryPoints: ["title.js"],
outfile: "out.js",
// bundle: false,
loader: { ".js": "jsx" },
plugins: [plugin1, plugin2],
});
// 最终只会输出p1 resolvedResolve 参数
当 esbuild 调用由注册的回调时 onResolve,将会为这些参数提供有关导入路径的信息
- path 这是来自底层代码的没有解析路径
- namespace 这是包含要解析的此导入模块的命名空间
onLoad 回调
- onLoad 将为每个未标记为外部的唯一路径/命名空间对运行添加回调
- 它的工作是返回模块内容并告诉 esbuild 如何解析
- 回调可以在不提供内容的情况下返回。这样加载模块的责任传递到下一个注册的回调。对于给定的模块,onLoad 所有插件的所有回调都将按照他们注册的顺序运行,直到有人负责加载模块。如果没有回调返回模块内容,esbuild 件运行默认的模块加载逻辑
- 如果 load 回调中返回了内容,后续的 load 回调也不会再执行
js
const plugin1 = {
name: "p1",
setup(build) {
build.onResolve({ filter: /.js$/ }, () => {
console.log("p1 resolve1");
});
build.onResolve({ filter: /.js$/ }, () => {
console.log("p1 resolve2");
return {
path: "C:/Users/Administrator/Desktop/test/title2.js",
};
});
build.onLoad({ filter: /.js$/ }, async ({ path }) => {
const contents = await fs.readFile(path);
console.log(contents.toString(), "p1 load1");
return {
contents,
};
});
build.onLoad({ filter: /.js$/ }, (arg) => {
console.log("p1 load2");
});
},
};
// 只会输出p1 load1onLoad 选项
- filter 每个回调都必须提供过滤器
- namespace 这是可选的,如果提供,回调仅在提供的命名空间中模块内的路径上运行
load 结果
- contents 将此设置为字符串以指定模块的内容。如果设置了此项,则不会针对此解析路径运行更多加载回调。如果未设置,esbuild 将继续运行后续注册的回调,最终如果都没有设置内容,解析的路径在 file 命名空间中,则将默认从文件系统加载内容
- loader 告诉 esbuild 如何解析内容。例如,js 加载器将内容解释为 JavaScript,css 加载器将内容解释为 CSS。
过滤器
- 每个回调都必须提供一个正则作为过滤器。当路径与其不匹配,esbuild 会跳过回调的调用
- 命名空间也可以用于过滤。回调必须提供过正则,也可以选择命名空间进一步限制匹配路径
envPlugin
js
// main.js
import { PATH } from "env";
console.log(`PATH is ${PATH}`);
// index.js
let envPlugin = {
name: "env",
setup(build) {
// 拦截名为env的导入路径,以便esbuild不会尝试将它们映射到文件系统位置
// 用env-ns名称空间标记它们,以便为该插件保留它们
build.onResolve({ filter: /^env$/ }, (args) => ({
path: args.path,
namespace: "env-ns",
}));
//加载带有env-ns名称空间标记的路径,它们的行为就像指向包含环境变量的JSON文件一样
build.onLoad({ filter: /.*/, namespace: "env-ns" }, () => ({
contents: JSON.stringify(process.env),
loader: "json",
}));
},
};
require("esbuild")
.build({
entryPoints: ["entry.js"],
bundle: true,
outfile: "out.js",
plugins: [envPlugin],
})
.catch(() => process.exit(1));其他
具体详细文档参考 es-build