Babel

Add Babel only when you need transforms or plugins that SWC does not cover. Keep SWC as the default pipeline, then scope Babel to the files that need it.

When Babel is a good fit

  • You depend on Babel-only plugins or presets.
  • You are migrating an existing Babel-heavy project incrementally.
  • You want targeted transforms for specific file types (for example MDX).

Babel capabilities

Capability What it gives you
Targeted transforms Run Babel for specific file types (for example MDX) without replacing the full build pipeline
Plugin ecosystem access Use Babel-only presets/plugins from existing web projects
Incremental migration Move legacy Babel extension projects to Extension.js in smaller steps
Rspack integration hook Configure Babel through extension.config.* config hook

Example setup

Install Babel dependencies:

npm
yarn
pnpm
bun
npm install -D @babel/core @babel/preset-env babel-loader

Create babel.config.json:

{
  "presets": ["@babel/preset-env"]
}

Wire Babel into extension.config.js for MDX only:

export default {
  config: (config) => {
    config.module.rules.push({
      test: /\.mdx$/,
      use: ["babel-loader", "@mdx-js/loader"],
    });
    return config;
  },
};

Video demo soon: targeted Babel integration

Replace SWC for JS/TS only if required

Use this pattern only when you need Babel to process JS/TS entry files directly:

export default {
  config: (config) => {
    config.module.rules = [
      {
        test: /\.[jt]sx?$/,
        exclude: /node_modules/,
        use: [{ loader: "babel-loader" }],
      },
      ...config.module.rules.filter(
        (rule) => !String(rule?.test || "").includes("[jt]sx"),
      ),
    ];
    return config;
  },
};

Best practices

  • Prefer targeted Babel usage before replacing the default JS/TS pipeline.
  • Keep Babel rules explicit so loader ordering stays predictable.
  • Reuse Babel only where migration or plugin compatibility requires it.

Next steps