Plugin development
Rsbuild's architecture is centered on a plugin system. Most of Rsbuild's functionality is implemented through plugins, which keeps the core lightweight while providing flexible extensibility.
Rsbuild plugins are functions that can register hooks at different stages, listen to events, and execute custom logic. If you want to modify the default behavior, add new features, or integrate third-party tools, plugins provide a comprehensive API to fulfill these requirements.
Comparison
Before developing a Rsbuild plugin, you may have been familiar with the plugin systems of tools such as webpack, Vite, esbuild, etc.
Rsbuild's plugin API is similar to esbuild's, and compared with webpack or Rspack plugins, Rsbuild's plugin API is simpler and easier to get started with.
From a functional perspective, Rsbuild's plugin API mainly revolves around Rsbuild's operation process and build configuration, providing various hooks for extension. On the other hand, Rspack's plugin API is more complex and comprehensive, capable of modifying every aspect of the bundling process.
Rspack plugins can be integrated into Rsbuild plugins. If the hooks provided by Rsbuild do not meet your requirements, you can also implement the functionality using Rspack plugin and register Rspack plugins in the Rsbuild plugin:
Developing plugins
Plugins provide a function similar to (options?: PluginOptions) => RsbuildPlugin as an entry point.
Plugin example
Registering the plugin:
Plugin structure
Function-based plugins can accept an options object and return a plugin instance, managing internal state through closures.
The roles of each part are as follows:
- The
nameproperty is used to label the plugin's name. setupserves as the main entry point for the plugin logic.- The
apiobject contains various hooks and utility functions.
Naming convention
The naming convention for plugins is as follows:
- The function of the plugin is named
pluginAbcand exported by name. - The
nameof the plugin follows the formatscope:foo-barorplugin-foo-bar, addingscope:can avoid naming conflicts with other plugins.
Here is an example:
The name of official Rsbuild plugins uniformly uses rsbuild: as a prefix, for example, rsbuild:react corresponds to @rsbuild/plugin-react.
Template repository
rsbuild-plugin-template is a minimal Rsbuild plugin template repository that you can use as a basis for developing your Rsbuild plugin.
Environment plugin
Rsbuild supports building outputs for multiple environments at the same time, and supports add plugins for specified environment.
If you want the plugin you develop to support use as an Environment plugin, you need to pay attention to the following points:
- Each environment has its own Rsbuild config:
- Use environment context instead of
getRsbuildConfigto get environment information. - When modifying the Rsbuild config for a specific environment, prioritize using modifyEnvironmentConfig instead of modifyRsbuildConfig to avoid affecting other environments.
- Use environment context instead of
- Be aware of side effects, your plugin code may be executed multiple times:
- When the same plugin is registered multiple times in different environments, it will be regarded as multiple Rsbuild plugins (even if they point to the same plugin instance), because they have different Rsbuild environment contexts.
Here is an example:
Reference other plugins
Rsbuild's plugins config supports passing a nested array, which means you can reference and register other Rsbuild plugins within your plugin.
For example, register pluginBar within pluginFoo:
Lifetime hooks
Rsbuild internally uses lifecycle hooks to schedule tasks, and plugins can also register hooks to take part in any stage of the workflow and implement their own features.
The full list of Rsbuild's lifetime hooks can be found in the API References.
Rsbuild does not take over the hooks of the underlying Rspack, whose documents can be found here: Rspack Plugin API.
Migrate Vite plugin
See Migrate Vite plugin to learn how to migrate a Vite plugin to Rsbuild plugin.
Use Rsbuild config
Custom plugins usually receive their options from the parameters passed to the initialization function, so you can define and use those arguments however you like.
Sometimes a plugin needs to read or modify Rsbuild's configuration. To do that effectively, it's helpful to understand how Rsbuild generates and consumes its config:
- Read, parse config and merge with default values.
- Plugins modify the config by
api.modifyRsbuildConfig(...). - Normalize the config and provide it to consume, then the config can no longer be modified.
Refer to this tiny example:
There are 3 ways to use Rsbuild config:
- register callback with
api.modifyRsbuildConfig(config => {})to modify config. - use
api.getRsbuildConfig()to get Rsbuild config. - use
api.getNormalizedConfig()to get finally normalized config.
When normalized, the config object is merged with the default values again and most optional properties are removed, ensuring those fields are always available. For pluginUploadDist, part of its type looks like:
The return type of getNormalizedConfig() differs slightly from RsbuildConfig; it's narrower because defaults have already been applied. You don't need to provide default values when you use it.
Therefore, the best way to use configuration options is to:
- Modify the config with
api.modifyRsbuildConfig(config => {}). - Read
api.getNormalizedConfig()as the actual config used by the plugin later in its lifecycle.
Modify Rspack configuration
Rsbuild plugin allows you to modify the built-in Rspack configuration, including:
- api.modifyRspackConfig: Modify the Rspack configuration object.
- api.modifyBundlerChain: Modify the Rspack configuration through rspack-chain.
Example
For example, register eslint-rspack-plugin via Rsbuild plugin:
Extending plugin API
When building custom tools on top of Rsbuild's JavaScript API, you may want to extend the existing plugin API to provide additional capabilities — for example, exposing utility functions or sharing context objects.
You can achieve this by using the rsbuild.expose() method on the Rsbuild instance.
This method works the same way as the plugin's api.expose(), allowing you to expose custom methods or objects to Rsbuild plugins.
For example, you can expose getState and setCount methods:
Plugins can then access these extended APIs using the api.useExposed() method:

