# Esbuild Plugin

import Esbuild from '@en/shared/esbuild.md';

<Esbuild />

:::tip Recommend using SWC
We recommend using SWC to transform and minify code rather than esbuild, because SWC supports more syntaxes, provides better code compression, and the compiled code has better compatibility.

Therefore, we recommend that you use SWC instead of esbuild, please refer to [SWC Plugin](plugins/plugin-swc) for usage.

:::

## Quick Start

### Used in Modern.js framework

The Modern.js framework integrates the Builder's esbuild plugin by default, so you don't need to manually install and register the plugin, just use the [tools.esbuild](https://modernjs.dev/en/configure/app/tools/esbuild.html) configuration:

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

### Use via the Node API

If you use the Builder's Node API, you need to manually install and register the esbuild plugin.

#### Install

You can install the plugin with the following command:

```bash
# npm
npm install @modern-js/builder-plugin-esbuild -D

# yarn
yarn add @modern-js/builder-plugin-esbuild -D

# pnpm
pnpm add @modern-js/builder-plugin-esbuild -D
```

#### Register

Register esbuild plugins through the `addPlugins` method:

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

// add the plugin to the builder instance
builder.addPlugins([builderPluginEsbuild()]);
```

## Config

The plugin will enable code transformation and minification by default. You can also customize the behavior of the plugin through configuration.

### loader

- **Type:**

```ts
type LoaderOptions = EsbuildLoaderOptions | false | undefined;
```

- **Default:**

```ts
const defaultOptions = {
  target: 'es2015',
  charset: builderConfig.output.charset,
};
```

This config is used to enable JavaScript/TypeScript transformation, which will replace babel-loader and ts-loader with esbuild-loader.

If you want to modify the options, you can check the [esbuild-loader documentation](https://github.com/privatenumber/esbuild-loader#loader).

#### Set JSX Format

When using esbuild for transformation, esbuild will read the `compilerOptions.jsx` field in `tsconfig.json` to determine which JSX syntax to use.

Therefore, you need to set the correct JSX syntax in `tsconfig.json`.

For example, React projects need to set `compilerOptions.jsx` to `react-jsx`:

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

#### Set the target environment

Use the `target` option to set the target environment for transformation. `target` can be set directly to the JavaScript language version, such as `es6`, `es2020`; it can also be set to several target environments, each target environment is an environment name followed by a version number, such as `['chrome58', 'edge16' ,'firefox57']`. For a detailed introduction of the `target` option, please refer to [esbuild - target](https://esbuild.github.io/api/#target).

target supports setting to the following environments:

- chrome
- edge
- firefox
- ie
- ios
- node
- opera
- safari

```ts
builderPluginEsbuild({
  loader: {
    target: 'chrome61',
  },
});
```

#### Disable transformation

Set `loader` to `false` to disable esbuild transformation, and Builder will continue to use Babel to transform the code.

```ts
builderPluginEsbuild({
  loader: false,
});
```

### minimize

- **Type:**

```ts
type MinimizeOptions = EsbuildMinifyOptions | false | undefined;
```

- **Default:**

```ts
const defaultOptions = {
  css: true,
  target: 'es2015',
  format: builderTarget === 'web' ? 'iife' : undefined,
};
```

This option is used to enable minification for JavaScript and CSS.

If you want to modify the options, you can check the [esbuild-loader documentation](https://github.com/privatenumber/esbuild-loader#minifyplugin).

#### Set the target environment

Use the `target` option to set the target environment for minification.

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

#### Disable minification

Set `minimize` to `false` to disable esbuild minification, and Builder will continue to use Terser to minify the code.

```ts
builderPluginEsbuild({
  minimize: false,
});
```

## Limitations

Although esbuild can significantly improve the build performance of existing webpack projects, it still has certain limitations that require special attention.

### Compatibility

As a compiler (i.e. `loader` capability), esbuild usually supports at least ES2015 (that is, ES6) syntax, and does not have the ability to automatically inject Polyfill.. If the production environment needs to downgrade to ES5 and below syntax, it is recommended to use SWC compilation.

You can specify the target syntax version by following config:

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

As a code minify tool (i.e. `minimize` capability), esbuild can minify the code in production environment, and usually supports ES2015 syntax at least.

If you set the compressed `target` to `es5`, you need to ensure that all codes have been compiled to ES5 codes, otherwise it will cause esbuild compilation error: `Transforming 'xxx' to the configured target environment ("es5") is not supported yet `.

Therefore, for projects that need to be compatible with ES5 and below syntax in the production environment, please be careful to enable the minimize capability, and it is recommended to use SWC compression.

You can specify the target syntax version by following config:

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

:::danger Caution
Projects that need to be compatible with ES5 and below syntax in the production environment need to be careful to turn on the minimize config.
:::

### Not support Babel plugins

As a compiler, the syntax transformation function of the original Babel plugins such as `babel-plugin-import` is not available after esbuild is turned on. And since the bottom layer of the plugin uses esbuild's `Transform API`, it does not support esbuild plugins to customize the compilation process.

If you have requirements related to Babel plugins such as `babel-plugin-import`, you can use the SWC plugin.

### Bundle Size

Although the compression speed of esbuild is faster, the compression ratio of esbuild is lower than that of terser, so the bundle size will increase, please use it according to the scenes. Generally speaking, esbuild is more suitable for scenes that are not sensitive to bundle size.

You can refer to [minification-benchmarks](https://github.com/privatenumber/minification-benchmarks) for a detailed comparison between minimizers.
