For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /plugins/low-level-plugins.md.
close

Low-level plugins

These plugins are publicly exposed low-level building blocks that Rspack primarily uses to implement target presets, runtime templates, child compilers, and higher-level plugins.

Usage guidance

For most application builds, prefer the corresponding high-level configuration. Direct use is mainly intended for custom compilers, child compilers, and advanced integrations.

Categories of low-level plugins:

environment

Plugins affecting the compiler environment and runtime target.

ElectronTargetPlugin

new rspack.electron.ElectronTargetPlugin(context);

ElectronTargetPlugin keeps Electron built-in modules external so Electron can load them at runtime. Pass 'main', 'preload', or 'renderer' to externalize the additional modules available in that process.

The externalsPresets.electron, externalsPresets.electronMain, externalsPresets.electronRenderer, and externalsPresets.electronPreload options apply this plugin internally.

For a regular Electron application, prefer the corresponding target:

rspack.config.mjs
export default {
  target: 'electron-main',
  entry: './src/main.js',
};

When configuring a child compiler directly, apply the plugin to that compiler:

new compiler.rspack.electron.ElectronTargetPlugin('main').apply(childCompiler);

NodeEnvironmentPlugin

new rspack.node.NodeEnvironmentPlugin(options);

NodeEnvironmentPlugin installs infrastructure logging, a cached Node.js input file system, the Node.js fs module as the output file system, and a watch file system on a compiler. The rspack() API applies it automatically to the root compiler.

When a custom compiler needs its own Node.js file-system environment, pass its normalized infrastructure logging options and apply the plugin directly:

new compiler.rspack.node.NodeEnvironmentPlugin({
  infrastructureLogging: childCompiler.options.infrastructureLogging,
}).apply(childCompiler);

This plugin configures compiler I/O and logging; it does not set the JavaScript runtime target. Use NodeTargetPlugin when Node.js built-in modules should remain external.

NodeTargetPlugin

new rspack.node.NodeTargetPlugin();

NodeTargetPlugin keeps Node.js built-in modules and requests using the node: scheme external so the Node.js runtime loads them instead of Rspack bundling them. The externalsPresets.node option applies this plugin internally.

For a regular Node.js application, prefer the node target:

rspack.config.mjs
export default {
  target: 'node',
  entry: './src/index.js',
};

When configuring a child compiler directly, apply the plugin to that compiler:

new compiler.rspack.node.NodeTargetPlugin().apply(childCompiler);

entry

Plugins that add entry chunks to the compilation.

DynamicEntryPlugin

new rspack.DynamicEntryPlugin(context, entry);

DynamicEntryPlugin calls an entry function during every make event and adds the returned entries to the compilation. This allows the entry list to change between watch rebuilds.

The direct API receives normalized entry descriptions, so each import value is an array:

rspack.config.mjs
import { rspack } from '@rspack/core';

const context = process.cwd();

export default {
  context,
  entry: {},
  plugins: [
    new rspack.DynamicEntryPlugin(context, async () => ({
      main: {
        import: ['./src/index.js'],
      },
    })),
  ],
};

For a regular build, prefer an entry function, which Rspack normalizes and passes to this plugin automatically.

EntryOptionPlugin

new rspack.EntryOptionPlugin();

EntryOptionPlugin handles the entryOption compiler hook. It applies an EntryPlugin for each static entry request or a DynamicEntryPlugin for a function entry. Rspack applies it automatically to the root compiler.

The static applyEntryOption helper is useful when adding normalized entries to a child compiler:

const childOptions = compiler.rspack.config.getNormalizedRspackOptions({
  entry: {
    child: './src/child.js',
  },
});

compiler.rspack.EntryOptionPlugin.applyEntryOption(
  childCompiler,
  compiler.context,
  childOptions.entry,
);

output

Plugins affecting generated modules, chunks, and runtime loading.

EnableChunkLoadingPlugin

new rspack.javascript.EnableChunkLoadingPlugin(type);

EnableChunkLoadingPlugin enables the runtime modules required by a chunk-loading type. Rspack normally applies it for the types collected in output.enabledChunkLoadingTypes.

The supported built-in types are 'jsonp', 'import-scripts', 'require', 'async-node', and 'import'.

Direct application is useful when a dynamic entry selects a type that Rspack cannot discover while normalizing the configuration:

rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  entry: () => ({
    main: {
      import: './src/index.js',
      chunkLoading: 'jsonp',
    },
  }),
  output: {
    chunkLoading: false,
  },
  plugins: [new rspack.javascript.EnableChunkLoadingPlugin('jsonp')],
};

For a custom chunk-loading implementation, call EnableChunkLoadingPlugin.setEnabled(compiler, type) after installing its runtime hooks. This method only registers the type; it does not implement chunk loading.

EnableLibraryPlugin

new rspack.library.EnableLibraryPlugin(type);

EnableLibraryPlugin registers a library output type with the compiler. Rspack normally applies it for the types collected in output.enabledLibraryTypes.

The following dynamic entry selects the 'var' library type and enables it explicitly because Rspack cannot inspect a function entry during configuration normalization:

src/index.js
export const add = (a, b) => a + b;
rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  entry: () => ({
    main: {
      import: './src/index.js',
      library: {
        name: 'MathLibrary',
        type: 'var',
      },
    },
  }),
  plugins: [new rspack.library.EnableLibraryPlugin('var')],
};

For a regular library build, prefer output.library, which automatically enables its library type.

EnableWasmLoadingPlugin

new rspack.wasm.EnableWasmLoadingPlugin(type);

EnableWasmLoadingPlugin enables the runtime modules required by a WebAssembly loading type. Rspack normally applies it for the types collected in output.enabledWasmLoadingTypes.

The supported types are 'fetch', 'async-node', and 'universal'.

The following example sets output.wasmLoading to false to disable automatic setup, then directly applies EnableWasmLoadingPlugin to install the 'fetch' loading runtime:

src/index.js
import { add } from './add.wasm';

console.log(add(1, 2));
rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  target: 'web',
  entry: './src/index.js',
  experiments: {
    asyncWebAssembly: true,
  },
  output: {
    wasmLoading: false,
  },
  plugins: [new rspack.wasm.EnableWasmLoadingPlugin('fetch')],
};

For a regular build, prefer output.wasmLoading, which automatically enables the selected type.

EvalDevToolModulePlugin

new rspack.EvalDevToolModulePlugin(options);

EvalDevToolModulePlugin wraps each non-external JavaScript module in eval and appends a sourceURL, allowing browser developer tools to display the original module name. Setting devtool: 'eval' applies this plugin automatically.

The following configuration applies it directly and uses dashboard as the source URL namespace:

rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  mode: 'development',
  devtool: false,
  plugins: [
    new rspack.EvalDevToolModulePlugin({
      namespace: 'dashboard',
    }),
  ],
};

The moduleFilenameTemplate and sourceUrlComment options can customize the generated module URL and comment format.

FetchCompileAsyncWasmPlugin

new rspack.web.FetchCompileAsyncWasmPlugin();

FetchCompileAsyncWasmPlugin adds the browser runtime that fetches and compiles asynchronous WebAssembly modules. EnableWasmLoadingPlugin('fetch') applies this implementation internally.

This example disables automatic WebAssembly loading setup and installs the fetch implementation directly:

src/index.js
import { add } from './add.wasm';

console.log(add(1, 2));
rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  target: 'web',
  entry: './src/index.js',
  experiments: {
    asyncWebAssembly: true,
  },
  output: {
    wasmLoading: false,
  },
  plugins: [new rspack.web.FetchCompileAsyncWasmPlugin()],
};

For a regular web build, prefer output.wasmLoading: 'fetch', which enables the same runtime automatically.

JsonpTemplatePlugin

new rspack.web.JsonpTemplatePlugin();

JsonpTemplatePlugin configures browser output for child compilers. It sets output.chunkLoading to 'jsonp', applies the 'array-push' chunk format, and enables the required JSONP chunk-loading runtime.

The following browser entry creates an asynchronous chunk:

src/browser-child.js
document.querySelector('button').addEventListener('click', async () => {
  const { message } = await import('./message.js');
  console.log(message);
});
src/message.js
export const message = 'Hello from the child compiler';

This configuration creates a child compiler and applies JsonpTemplatePlugin directly:

rspack.config.mjs
export default {
  target: 'web',
  entry: {},
  plugins: [
    (compiler) => {
      compiler.hooks.make.tapAsync(
        'BrowserChildCompiler',
        (compilation, callback) => {
          const childCompiler = compilation.createChildCompiler(
            'browser-child',
            {
              filename: 'browser-child.js',
              chunkFilename: '[name].browser-child.js',
            },
            [
              new compiler.rspack.web.JsonpTemplatePlugin(),
              new compiler.rspack.EntryPlugin(
                compiler.context,
                './src/browser-child.js',
                { name: 'browser-child' },
              ),
            ],
          );

          childCompiler.runAsChild((error) => callback(error));
        },
      );
    },
  ],
};

JsonpTemplatePlugin makes the child compiler emit array-push chunks and load asynchronous chunks by adding script elements to the page.

For a regular web build, prefer target: 'web'. It selects the 'array-push' chunk format and 'jsonp' chunk loading through Rspack's target defaults. Setting output.chunkLoading: 'jsonp' only selects the loading implementation; it does not apply JsonpTemplatePlugin or choose the chunk format.

NodeTemplatePlugin

new rspack.node.NodeTemplatePlugin(options);

NodeTemplatePlugin configures Node.js output for child compilers. It applies the 'commonjs' chunk format, sets output.chunkLoading to 'require' by default, and enables the required chunk-loading runtime.

asyncChunkLoading

  • Type: boolean
  • Default: false

When asyncChunkLoading is true, the plugin uses 'async-node' chunk loading instead of 'require'.

The following Node.js entry creates an asynchronous chunk:

src/node-child.js
async function main() {
  const { run } = await import('./task.js');
  run();
}

main();
src/task.js
export function run() {
  console.log('Task completed');
}

This configuration creates a child compiler and applies NodeTemplatePlugin directly:

rspack.config.mjs
export default {
  target: 'node',
  entry: {},
  plugins: [
    (compiler) => {
      compiler.hooks.make.tapAsync(
        'NodeChildCompiler',
        (compilation, callback) => {
          const childCompiler = compilation.createChildCompiler(
            'node-child',
            {
              filename: 'node-child.js',
              chunkFilename: '[name].node-child.js',
            },
            [
              new compiler.rspack.node.NodeTemplatePlugin(),
              new compiler.rspack.EntryPlugin(
                compiler.context,
                './src/node-child.js',
                { name: 'node-child' },
              ),
            ],
          );

          childCompiler.runAsChild((error) => callback(error));
        },
      );
    },
  ],
};

NodeTemplatePlugin makes the child compiler emit CommonJS chunks and load asynchronous chunks with require.

For a regular Node.js build, prefer target: 'node'. It selects the 'commonjs' chunk format and 'require' chunk loading through Rspack's target defaults. Setting output.chunkLoading: 'require' only selects the loading implementation; it does not apply NodeTemplatePlugin or choose the chunk format.

WebWorkerTemplatePlugin

new rspack.webworker.WebWorkerTemplatePlugin();

WebWorkerTemplatePlugin configures Web Worker output for child compilers. It sets output.chunkLoading to 'import-scripts', applies the 'array-push' chunk format, and enables the required importScripts chunk-loading runtime.

The following worker creates an asynchronous chunk:

src/worker-child.js
self.onmessage = async ({ data }) => {
  const { double } = await import('./math.js');
  self.postMessage(double(data));
};
src/math.js
export const double = (value) => value * 2;

This configuration creates a child compiler and applies WebWorkerTemplatePlugin directly:

rspack.config.mjs
export default {
  target: 'webworker',
  entry: {},
  plugins: [
    (compiler) => {
      compiler.hooks.make.tapAsync(
        'WorkerChildCompiler',
        (compilation, callback) => {
          const childCompiler = compilation.createChildCompiler(
            'worker-child',
            {
              filename: 'worker-child.js',
              chunkFilename: '[name].worker-child.js',
            },
            [
              new compiler.rspack.webworker.WebWorkerTemplatePlugin(),
              new compiler.rspack.EntryPlugin(
                compiler.context,
                './src/worker-child.js',
                { name: 'worker-child' },
              ),
            ],
          );

          childCompiler.runAsChild((error) => callback(error));
        },
      );
    },
  ],
};

WebWorkerTemplatePlugin makes the child compiler emit array-push chunks and load asynchronous chunks with importScripts.

For a regular Web Worker build, prefer target: 'webworker'. It selects the 'array-push' chunk format and 'import-scripts' chunk loading through Rspack's target defaults. Setting output.chunkLoading: 'import-scripts' only selects the loading implementation; it does not apply WebWorkerTemplatePlugin or choose the chunk format.

loader

Plugins that customize the context in which loaders execute.

LoaderOptionsPlugin

new rspack.LoaderOptionsPlugin(options);

LoaderOptionsPlugin copies custom option fields onto the loader context for resources matching test, include, and exclude. The matching fields themselves are used only as filters and are not copied.

This loader reads a custom message property from its context:

loaders/message-loader.cjs
module.exports = function () {
  return `export default ${JSON.stringify(this.message)};`;
};

The plugin provides that property only while processing .message files:

rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  entry: './src/welcome.message',
  module: {
    rules: [
      {
        test: /\.message$/,
        use: './loaders/message-loader.cjs',
      },
    ],
  },
  plugins: [
    new rspack.LoaderOptionsPlugin({
      test: /\.message$/,
      message: 'Hello from the loader',
    }),
  ],
};

This plugin mainly supports loaders that read custom properties from this. New loaders should usually receive values through their own loader options.

LoaderTargetPlugin

new rspack.LoaderTargetPlugin(target);

LoaderTargetPlugin assigns target to this.target in every loader context. It is useful when a custom compiler needs loaders to observe a target that differs from the compiler's configured target.

The following loader replaces its input with the target it observes:

loaders/target-loader.cjs
module.exports = function () {
  return `console.log(${JSON.stringify(this.target)});`;
};

Although the build target is web, this plugin makes the loader receive 'node':

rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  target: 'web',
  entry: './src/index.js',
  module: {
    rules: [
      {
        test: /index\.js$/,
        use: './loaders/target-loader.cjs',
      },
    ],
  },
  plugins: [new rspack.LoaderTargetPlugin('node')],
};

For a regular build, prefer the top-level target option.

module federation

These plugins implement the exposes, remotes, and shared parts of Module Federation. For regular application builds, prefer ModuleFederationPlugin, which configures these low-level plugins together.

ContainerPlugin

new rspack.container.ContainerPlugin(options);

ContainerPlugin creates a container entry that exposes local modules through the Module Federation get and init interface. It is the low-level implementation of the exposes option.

This configuration emits remoteEntry.js and exposes src/Button.js as ./Button:

rspack.config.mjs
import { container } from '@rspack/core';

export default {
  entry: {},
  plugins: [
    new container.ContainerPlugin({
      name: 'catalog',
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/Button.js',
      },
    }),
  ],
};

ContainerReferencePlugin

new rspack.container.ContainerReferencePlugin(options);

ContainerReferencePlugin registers remote containers as externals and adds the runtime needed to load modules from them. It is the low-level implementation of the remotes option.

With the following configuration, an import such as import('catalog/Button') loads ./Button from the remote container:

rspack.config.mjs
import { container } from '@rspack/core';

export default {
  entry: './src/index.js',
  plugins: [
    new container.ContainerReferencePlugin({
      remoteType: 'script',
      remotes: {
        catalog: 'catalog@http://localhost:3001/remoteEntry.js',
      },
    }),
  ],
};

ConsumeSharedPlugin

new rspack.sharing.ConsumeSharedPlugin(options);

ConsumeSharedPlugin resolves configured module requests from a share scope. It can enforce version and singleton requirements and use a local module as a fallback when no suitable provider is available.

This example consumes react as a singleton from the default share scope and falls back to the locally installed package without checking its version:

rspack.config.mjs
import { sharing } from '@rspack/core';

export default {
  entry: './src/index.js',
  plugins: [
    new sharing.ConsumeSharedPlugin({
      consumes: {
        react: {
          import: 'react',
          requiredVersion: false,
          singleton: true,
        },
      },
    }),
  ],
};

ProvideSharedPlugin

new rspack.sharing.ProvideSharedPlugin(options);

ProvideSharedPlugin registers local modules and their versions in a share scope so other builds can consume them. It is the provider half of the shared option.

The shorthand form below provides the locally installed react package under the react share key and infers its version from the package metadata:

rspack.config.mjs
import { sharing } from '@rspack/core';

export default {
  plugins: [
    new sharing.ProvideSharedPlugin({
      provides: ['react'],
    }),
  ],
};

SharePlugin

new rspack.sharing.SharePlugin(options);

SharePlugin applies both ConsumeSharedPlugin and ProvideSharedPlugin for the same shared configuration. It is the low-level equivalent of ModuleFederationPlugin's shared option.

This example provides the local react package as a fallback and consumes a singleton instance from the default share scope:

rspack.config.mjs
import { sharing } from '@rspack/core';

export default {
  plugins: [
    new sharing.SharePlugin({
      enhanced: false,
      shared: {
        react: {
          requiredVersion: false,
          singleton: true,
        },
      },
    }),
  ],
};

TreeShakingSharedPlugin

new rspack.sharing.TreeShakingSharedPlugin(options);
Stability: Experimental

TreeShakingSharedPlugin creates independent builds and optimizes exports for Module Federation shared dependencies. ModuleFederationPlugin applies it automatically when at least one shared dependency enables treeShaking.

Options

  • mfConfig: The ModuleFederationPluginOptions used to configure the shared dependencies and output.
  • secondary: Whether to perform a second tree-shaking pass during the independent build. The default is false.
  • onBuildAssets: A callback invoked with the generated shared fallback assets.

Direct application is mainly intended for deployment integrations that perform a secondary build. It must be combined with a sharing plugin so TreeShakingSharedPlugin can collect the shared modules to build:

src/index.js
import { add } from 'lodash-es';

console.log(add(1, 2));
rspack.config.mjs
import { sharing } from '@rspack/core';

const shared = {
  'lodash-es': { treeShaking: { mode: 'server-calc' } },
};

export default {
  entry: './src/index.js',
  plugins: [
    new sharing.SharePlugin({
      enhanced: true,
      shared,
    }),
    new sharing.TreeShakingSharedPlugin({
      secondary: true,
      mfConfig: {
        name: 'app',
        shared,
        library: { type: 'var', name: 'App' },
      },
    }),
  ],
};

The plugin creates an independent build only for shared dependencies that enable treeShaking and retain a local implementation. Direct use does not generate Module Federation stats or manifest files. When ModuleFederationPlugin applies it internally with manifest generation enabled, the plugin writes the generated fallback asset information into those files.

experiments

RemoveDuplicateModulesPlugin

new rspack.experiments.RemoveDuplicateModulesPlugin();
Stability: Experimental

RemoveDuplicateModulesPlugin finds modules that occur in the same set of multiple chunks and moves them into one reusable or newly created shared chunk. Rspack uses it internally for modern-module library output.

In this example, both entries import the same src/shared.js module. Disabling splitChunks makes RemoveDuplicateModulesPlugin responsible for extracting that duplicated module:

rspack.config.mjs
import { rspack } from '@rspack/core';

export default {
  entry: {
    admin: './src/admin.js',
    store: './src/store.js',
  },
  optimization: {
    splitChunks: false,
  },
  plugins: [new rspack.experiments.RemoveDuplicateModulesPlugin()],
};

This page is adapted from webpack documentation under the CC BY 4.0, with modifications.