Babel Plugin

Rsbuild uses SWC transpilation by default. When existing functions cannot meet the requirements, and some Babel presets or plugins need to be added for additional processing, you can use Rsbuild's Babel Plugin.

Quick Start

Install Plugin

You can install the plugin using the following command:

npm
yarn
pnpm
bun
npm add @rsbuild/plugin-babel -D

Register Plugin

You can register the plugin in the rsbuild.config.ts file:

rsbuild.config.ts
import { pluginBabel } from '@rsbuild/plugin-babel';

export default {
  plugins: [pluginBabel()],
};

Compilation Cache

After using the Babel plugin, Rsbuild will perform the Babel transpilation in addition to the standard SWC transpilation, which adds additional compilation overhead. This can cause a noticeable decrease in build speed.

To reduce the overhead of Babel transpilation, the @rsbuild/plugin-babel enables Babel compilation cache by default. If you want to disable the cache, you can set performance.buildCache to false:

rsbuild.config.ts
export default {
  performance: {
    buildCache: false,
  },
};

Options

babelLoaderOptions

Options passed to babel-loader, please refer to the babel-loader documentation for detailed usage.

  • Type: Object | Function
  • Default:
const defaultOptions = {
  babelrc: false,
  compact: false,
  configFile: false,
  plugins: [
    ['@babel/plugin-proposal-decorators', config.source.decorators],
    ...(isLegacyDecorators ? ['@babel/plugin-transform-class-properties'] : []),
  ],
  presets: [
    [
      '@babel/preset-typescript',
      {
        allExtensions: true,
        allowDeclareFields: true,
        allowNamespaces: true,
        isTSX: true,
        optimizeConstEnums: true,
      },
    ],
  ],
};

Function Type

When configuration is of type Function, the default Babel configuration will be passed as the first parameter. You can directly modify the configuration object or return an object as the final babel-loader configuration.

pluginBabel({
  babelLoaderOptions: (config) => {
    // Add a Babel plugin
    // note: the plugin have been added to the default config to support antd load on demand
    config.plugins ||= [];
    config.plugins.push([
      'babel-plugin-import',
      {
        libraryName: 'my-components',
        libraryDirectory: 'es',
        style: true,
      },
    ]);
  },
});

The second parameter of the function provides some more convenient utility functions. Please continue reading the documentation below.

TIP

The above example is just for reference, usually you don't need to manually configure babel-plugin-import, because the Rsbuild already provides a more general source.transformImport configuration.

Object Type

When configuration's type is Object, the config will be shallow merged with default config by Object.assign.

CAUTION

Note that Object.assign is a shallow copy and will completely overwrite the built-in presets or plugins array, please use it with caution.

pluginBabel({
  babelLoaderOptions: {
    plugins: [
      [
        'babel-plugin-import',
        {
          libraryName: 'my-components',
          libraryDirectory: 'es',
          style: true,
        },
      ],
    ],
  },
});

Util Functions

When configuration is a Function, the tool functions available for the second parameter are as follows:

addPlugins
  • Type: (plugins: BabelPlugin[]) => void

Add some Babel plugins. For example:

pluginBabel({
  babelLoaderOptions: (config, { addPlugins }) => {
    addPlugins([
      [
        'babel-plugin-import',
        {
          libraryName: 'my-components',
          libraryDirectory: 'es',
          style: true,
        },
      ],
    ]);
  },
});
addPresets
  • Type: (presets: BabelPlugin[]) => void

Add Babel preset configuration. (No need to add presets in most cases)

pluginBabel({
  babelLoaderOptions: (config, { addPresets }) => {
    addPresets(['@babel/preset-env']);
  },
});
removePlugins
  • Type: (plugins: string | string[]) => void

To remove the Babel plugin, just pass in the name of the plugin to be removed, you can pass in a single string or an array of strings.

pluginBabel({
  babelLoaderOptions: (config, { removePlugins }) => {
    removePlugins('babel-plugin-import');
  },
});
removePresets
  • Type: (presets: string | string[]) => void

To remove the Babel preset configuration, pass in the name of the preset to be removed, you can pass in a single string or an array of strings.

pluginBabel({
  babelLoaderOptions: (config, { removePresets }) => {
    removePresets('@babel/preset-env');
  },
});

include

  • Type: string | RegExp | (string | RegExp)[]
  • Default: undefined

Used to specify the files that need to be compiled by Babel.

Due to the performance overhead of Babel compilation, matching only certain files through include can reduce the number of modules compiled by Babel, thereby improving build performance.

For example, to only compile .custom.js files and ignore files under node_modules:

pluginBabel({
  include: /\.custom\.js$/,
  // recommended to exclude the node_modules to improve build performance
  exclude: /[\\/]node_modules[\\/]/,
});
TIP

When you configure the include or exclude options, Rsbuild will create a separate Rspack rule to apply babel-loader and swc-loader.

This separate rule is completely independent of the SWC rule built into Rsbuild and is not affected by source.include and source.exclude.

exclude

  • Type: string | RegExp | (string | RegExp)[]
  • Default: undefined

Used to specify the files that do not need to be compiled by Babel.

Due to the performance overhead of Babel compilation, excluding certain files through exclude can reduce the number of modules compiled by Babel, thereby improving build performance.

Debugging Configs

After modifying the babel-loader configuration, you can view the final generated configuration in Rsbuild debug mode.

First, enable debug mode by using the DEBUG=rsbuild option:

# Debug development mode
DEBUG=rsbuild pnpm dev

# Debug production mode
DEBUG=rsbuild pnpm build

Then open the generated rspack.config.web.mjs file and search for the babel-loader keyword to see the complete babel-loader configuration.

FAQ

Compilation Freezes

After using the babel plugin, if the compilation progress bar is stuck, but there is no Error log on the terminal, it is usually because an exception occurred during the compilation. In some cases, when Error is caught by webpack or other modules, the error log can not be output correctly. The most common scenario is that there is an exception in the Babel config, which is caught by webpack, and webpack swallows the Error in some cases.

Solution:

If this problem occurs after you modify the Babel config, it is recommended to check for the following incorrect usages:

  1. You have configured a plugin or preset that does not exist, maybe the name is misspelled, or it is not installed correctly.
// wrong example
pluginBabel({
  babelLoaderOptions: (config, { addPlugins }) => {
    // The plugin has the wrong name or is not installed
    addPlugins('babel-plugin-not-exists');
  },
});
  1. Whether multiple babel-plugin-imports are configured, but the name of each babel-plugin-import is not declared in the third item of the array.
// wrong example
pluginBabel({
  babelLoaderOptions: (config, { addPlugins }) => {
    addPlugins([
      ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es' }],
      [
        'babel-plugin-import',
        { libraryName: 'antd-mobile', libraryDirectory: 'es' },
      ],
    ]);
  },
});
// correct example
pluginBabel({
  babelLoaderOptions: (config, { addPlugins }) => {
    addPlugins([
      [
        'babel-plugin-import',
        { libraryName: 'antd', libraryDirectory: 'es' },
        'antd',
      ],
      [
        'babel-plugin-import',
        { libraryName: 'antd-mobile', libraryDirectory: 'es' },
        'antd-mobile',
      ],
    ]);
  },
});