Esbuild 插件

WARNING

当前文档中的 esbuild 功能已停止迭代,我们更推荐使用 Rspack + SWC 的方案,因为 Rspack + SWC 具备更好的构建性能、功能丰富度和产物兼容性。

请参考「使用 Rspack」了解更多。

esbuild 是一款基于 Golang 开发的前端构建工具,具有打包、编译和压缩 JavaScript 代码的功能,相比传统的打包编译工具,esbuild 在性能上有显著提升。在代码压缩方面,相比 webpack 内置的 terser 压缩器,esbuild 在性能上有数十倍的提升。

Modern.js Builder 提供了 esbuild 插件,让你能使用 esbuild 代替 babel-loader、ts-loader 和 terser 等库进行代码编译和压缩。在大型工程中启用 esbuild 后,可以大幅度减少代码编译和压缩所需的时间,同时有效避免 OOM (heap out of memory) 问题

快速开始

在 Modern.js 框架中使用

Modern.js 框架默认集成了 Builder 的 esbuild 插件,因此,你不需要手动安装和注册插件,只需要使用 tools.esbuild 配置项即可:

export default defineConfig({
  tools: {
    esbuild: {
      loader: {
        target: 'chrome61',
      },
      minimize: {
        target: 'chrome61',
      },
    },
  },
});

通过 Node API 使用

如果你直接使用了 Builder 的 Node API,那么需要手动安装和注册 esbuild 插件。

安装插件

你可以通过如下的命令安装插件:

npm
yarn
pnpm
bun
npm add @modern-js/builder-plugin-esbuild -D

注册插件

通过 addPlugins 方法来注册 esbuild 插件:

import { builderPluginEsbuild } from '@modern-js/builder-plugin-esbuild';

// 往 builder 实例上添加插件
builder.addPlugins([builderPluginEsbuild()]);

配置

插件默认会开启代码转译和代码压缩的功能,你也可以通过配置来自定义插件的行为。

loader

  • 类型:
type LoaderOptions = EsbuildLoaderOptions | false | undefined;
  • 默认值:
const defaultOptions = {
  target: 'es2015',
  charset: builderConfig.output.charset,
};

这个选项用于启用 JavaScript 和 TypeScript 的转译,启用时将会使用 esbuild-loader 替换 babel-loader 和 ts-loader。

如果你需要修改转译参数,可以查看 esbuild-loader 文档

设置 JSX 格式

在使用 esbuild 进行代码转译时,esbuild 默认会读取 tsconfig.json 中的 compilerOptions.jsx 字段,来决定使用哪种 JSX 语法。

因此,你需要在 tsconfig.json 中设置正确的 JSX 语法。

比如 React 项目,需要将 compilerOptions.jsx 设置为 react-jsx

{
  "compilerOptions": {
    "jsx": "react-jsx"
  }
}

修改目标环境

通过 target 选项来修改代码转译的目标环境。target 可以直接设置为 JavaScript 语言版本,比如 es6es2020;也可以设置为若干个目标环境,每个目标环境都是一个环境名称后跟一个版本号,比如 ['chrome58', 'edge16' ,'firefox57']target 字段的详细介绍可以参考 esbuild - target

target 支持设置为以下环境:

  • chrome
  • edge
  • firefox
  • ie
  • ios
  • node
  • opera
  • safari
builderPluginEsbuild({
  loader: {
    target: 'chrome61',
  },
});

关闭代码转译

loader 设置为 false 来关闭 esbuild 代码转译,此时 Builder 会继续使用 Babel 来进行代码转译。

builderPluginEsbuild({
  loader: false,
});

minimize

  • 类型:
type MinimizeOptions = EsbuildMinifyOptions | false | undefined;
  • 默认值:
const defaultOptions = {
  css: true,
  target: 'es2015',
  format: builderTarget === 'web' ? 'iife' : undefined,
};

这个选项用于启用 JavaScript 和 CSS 的代码压缩。

如果你需要修改压缩参数,可以查看 esbuild-loader 文档

修改目标环境

通过 target 选项来修改代码压缩的目标环境。

builderPluginEsbuild({
  minimize: {
    target: 'chrome61',
  },
});

关闭代码压缩

minimize 设置为 false 来关闭 esbuild 代码压缩,此时 Builder 会继续使用 Terser 进行代码压缩。

builderPluginEsbuild({
  minimize: false,
});

esbuild 局限性

虽然 esbuild 能给现有的 webpack 项目带来明显的构建性能提升,但这个工具在接入 Builder 时还存在一定的局限性,需要大家在接入的时候格外注意。

兼容性

使用 esbuild 进行代码转译时(即 loader 能力),esbuild 通常最低支持到 ES2015(即 ES6)语法,并且不具备自动注入 Polyfill 的能力。如果生产环境需要降级到 ES5 及以下的语法,建议使用 SWC 编译。

你可以通过如下的配置指定目标语法版本:

builderPluginEsbuild({
  loader: {
    target: 'es2015',
  },
});

使用 esbuild 进行代码压缩时(即 minimize 能力),esbuild 可以在生产环境中进行压缩和混淆,通常最低支持到 ES2015 语法。

如果设置压缩的 targetes5,需要保证所有代码已经被转义为 ES5 代码,否则会导致 esbuild 编译报错:Transforming 'xxx' to the configured target environment ("es5") is not supported yet

因此,对于生产环境需要兼容 ES5 及以下语法的项目,请谨慎开启 minimize 能力,建议使用 SWC 压缩。

你可以通过如下的配置指定目标语法版本:

builderPluginEsbuild({
  minimize: {
    target: 'es2015',
  },
});

不支持 Babel 插件

使用 esbuild 进行代码转译时,诸如 babel-plugin-import 等原有 Babel 插件的语法编译功能在开启 esbuild 后无法使用。并且由于 Builder 底层使用的是 esbuild 的 Transform API,因此不支持使用额外 esbuild 插件来进行自定义编译过程。

如果你有 babel-plugin-import 等 Babel 插件相关诉求,可以使用 SWC 插件。

产物体积

使用 esbuild 压缩虽然带来了构建效率上的提升,但 esbuild 的压缩比例是低于 terser 的,因此构建产物的体积会增大,请根据业务情况酌情使用。通常来说,esbuild 比较适合中后台等对体积不敏感的场景。

对于压缩工具之间的详细对比,可以参考 minification-benchmarks