新一代打包工具esbuild
日期:2021-08-05 14:30:00
更新:2021-08-05 14:30:00
标签:JavaScript
分类:JavaScript
esbuild官方描述的作用就是:一个JavaScript的打包和和压缩工具。esbuild使用golang开发,在打包的速度上非常快,我们熟悉的vite工具在dev模式下就是使用esbuild进行打包。

了解 esbuild
esbuild 是什么
esbuild 官方描述的作用就是:一个JavaScript的打包和和压缩工具。
esbuild 使用golang开发,在打包的速度上非常快,我们熟悉的vite工具在dev 模式下就是使用 esbuild 进行打包。
esbuild 的主要特征
- 在没有缓存的情况也能有极致的性能
- 支持 ES6 的 Tree shaking
- 原生支持 typescript 和 jsx 打包
- 支持 Source Map
- 代码压缩
- 支持定义插件
打包速度比较
esbuild 最主要的一个特征就是有极致的性能,那么它到底有多快,参考 esbuild 官方提供的一张图
可以看到,esbuild 的性能跟现在主流的打包工具相比,速度比他们快超过 100 倍。可见它在性能方面有多可怕。
因为现在主流的打包工具底层上执行还是在 js 的执行环境中,cpu 不能充分地得到使用,所以就会导致执行速度慢。
esbuild 使用
了解完 esbuild 概念,接下来了解一下如何使用 esbuild 的一些主要概念
API
-
transform
transform就是转换的意思,调用这个 API 能将ts,jsx等文件转换为 js 文件。
支持的文件有:
export type Loader =
| "js"
| "jsx"
| "ts"
| "tsx"
| "css"
| "json"
| "text"
| "base64"
| "file"
| "dataurl"
| "binary"
| "default";
使用 transform
首先我们创建一个测试的 TS 文件
const str: string = "Hello World";
使用transform转换为 js
exbuild ./test.ts --loader=ts
const esbuild = require('esbuild');
const fs = require('fs');
const path = require('path');
const filePath = path.resolve(__dirname, 'test.ts');
const code = esbuild.transformSync(fs.readFilesync(filePath), {
loader: 'ts',
})
console.log(code);
transform 还可以在转换代码的同时进行压缩代码(minify),制定代码的模块类型(format) 等等,部分的的配置如下:
interface TransformOptions {
loader?: Loader;
banner?: string;
footer?: string;
sourcemap?: boolean | "inline" | "external" | "both";
legalComments?: "none" | "inline" | "eof" | "linked" | "external";
sourceRoot?: string;
sourcesContent?: boolean;
minify?: boolean;
minifyWhitespace?: boolean;
minifyIdentifiers?: boolean;
minifySyntax?: boolean;
charset?: Charset;
treeShaking?: TreeShaking;
jsx?: "transform" | "preserve";
jsxFactory?: string;
jsxFragment?: string;
}
具体的描述可以看这里
-
build
build整合了transform后的代码,可以将一个或者多个文件转换并保存为文件。
使用:
esbuild test.ts --outfile=./dist/test.js
const esbuild = require('esbuild');
const path = require('path');
const result = esbuild.buildSync({
entryPoints: [path.resolve(__dirname, 'test.ts')],
outdir: path.resolve(__dirname, 'dist'),
});
console.log(result);
执行完后会生成转换后的代码文件到指定的目录,具体的配置参数可以点击这里
esbuild 插件(Plugins)
与其他打包工具一样,esbuild 也有plugin,plugin 会在build的时候提供一些钩子函数,让你可以在打包的某一个阶段去执行自定义的操作。
plugin提供了四个钩子,按顺序执行分别是:onStart,onResolve,onLoad,onEnd
现在我们就来写一个测试的插件:
const esbuild = require("esbuild");
const path = require("path");
const testPlugin = {
name: "testPlugin",
setup({ onStart, onResolve, onLoad, onEnd }) {
onStart(() => {
console.log("onStart");
});
onResolve({ filter: /.*/ }, (msg) => {
console.log("onResolve", msg);
});
onLoad({ filter: /.*/ }, (msg) => {
console.log("onLoad", msg);
});
onEnd((msg) => {
console.log("onEnd", msg);
});
},
};
esbuild.buildSync({
entryPoints: [path.resolve(__dirname, "test.ts")],
outdir: path.resolve(__dirname, "dist"),
bundle: true,
plugins: [testPlugin],
});
执行后返回

实战:利用 esbuild 打包 ts 项目
讲完 esbuild 的大概用法,接下来做一个实战项目。项目中大概的步骤:
- 1.将 typescript 项目打包成 js 文件
- 2.将打包后的文件放到 HTML 中运行这个 HTML。
首先来写一个插入节点的 ts 文件test.ts
(function () {
const app = document.querySelector("#app");
const div = document.createElement("div");
div.innerHTML = "<div>Hello World</div>";
app.appendChild(div);
})();
创建一个 html 文件
<!DOCTYPE html>
<html>
<head>
<title>test html</title>
</head>
<body>
<div id="app"></div>
<script src="{{scripts}}"></script>
</body>
</html>
接下来写打包逻辑
const esbuild = require("esbuild");
const path = require("path");
const fs = require("fs");
const HTML_PATH = path.resolve(__dirname, "index.html");
const TARGET_PATH = path.resolve(__dirname, "dist");
const OUTPUT_PATH = "./test.js";
const testPlugin = {
name: "testPlugin",
setup({ onEnd }) {
onEnd(({ errors }) => {
console.log(errors);
if (!errors.length) {
let data = fs.readFileSync(HTML_PATH, { encoding: "utf-8" });
data = data.replace(`{scripts}`, OUTPUT_PATH);
fs.writeFileSync(path.resolve(TARGET_PATH, "index.html"), data, {
encoding: "utf-8",
});
}
});
},
};
esbuild
.build({
entryPoints: [path.resolve(__dirname, "test.ts")],
outdir: path.resolve(__dirname, "dist"),
bundle: true,
plugins: [testPlugin],
})
.then((msg) => {
if (msg.length) throw new Error("compile error");
console.log("compile success");
});
执行 esbuild.js 文件

文件已经生成成功,打开 html 文件看一下有没有执行 js

代码成功执行

小结
本文主要介绍了esbuild打包工具。主要介绍了:
- esbuild 的性能比现在主流的打包工具要快得多
- esbuild 的 api 和用法
- esbuild 如何定义插件
- 利用 esbuild 打包一个 ts 项目
参考
- esbuild