Plugin API
Overview
Rolldown's plugin interface is almost fully compatible with Rollup's (detailed tracking here), so if you have written a Rollup plugin before, you already know how to write a Rolldown plugin!
A Rolldown plugin is an object that satisfies the plugin interface described below. A plugin should be distributed as a package which exports a function that can be called with plugin specific options and returns such an object.
Plugins allow you to customize Rolldown's behavior by, for example, transpiling code before bundling, or shimming a built-in module that is not available.
Example
The following example shows a Rolldown plugin that intercepts import requests to example-virtual-module and returns a custom content for it.
const id = 'example-virtual-module';
const resolvedId = '\0' + id;
export default function examplePlugin() {
return {
name: 'example-plugin', // this name will show up in logs and errors
resolveId(source) {
if (source === id) {
// this signals to Rolldown that this import should resolve to a module named `\0example-virtual-module`
return resolvedId;
}
return null; // other ids should be handled as usual
},
load(id) {
if (id === resolvedId) {
// the source code for `\0example-virtual-module`
return `export default 'Hello from ${id}';`;
}
return null; // other ids should be handled as usual
},
};
}import { defineConfig } from 'rolldown';
import examplePlugin from './rolldown-plugin-example.js';
export default defineConfig({
plugins: [examplePlugin()],
});Virtual Modules
This plugin implements a pattern which is commonly called "virtual modules". A virtual module is a module that does not exist on the file system and is instead resolved and provided by a plugin. In the example above, example-virtual-module is never read from disk because the plugin intercepts the import in resolveId and supplies the module’s source code in load. This pattern is useful for injecting helper functions.
Hook Filters
This example plugin does not use Hook Filters for simplicity. To improve performance, it is recommended to use them when possible.
Conventions
- Plugins should have a clear name with
rolldown-plugin-prefix. - Include
rolldown-pluginkeyword in the package.jsonkeywordsfield. - Make sure your plugin outputs correct source mappings if appropriate.
- If your plugin uses "virtual modules", prefix the module ID with
\0. This prevents other plugins from trying to process it. - (recommended) Plugins should be tested.
- (recommended) Plugins should be documented in English.
Plugin Interface
The Plugin interface has a required name property and multiple optional properties and hooks.
Hooks are methods defined on the plugin that can be used to interact with the build process. They are called at various stages of the build. Hooks can affect how a build is run, provide information about a build, or modify a build once complete. There are different kinds of hooks:
async: The hook may also return a Promise resolving to the same type of value; otherwise, the hook is marked assync.first: If several plugins implement this hook, the hooks are run sequentially until a hook returns a value other thannullorundefined.sequential: If several plugins implement this hook, all of them will be run in the specified plugin order. If a hook isasync, subsequent hooks of this kind will wait until the current hook is resolved.parallel: If several plugins implement this hook, all of them will be run in the specified plugin order. If a hook isasync, subsequent hooks of this kind will be run in parallel and not wait for the current hook.
Instead of a method, hooks can also be objects with a handler property. In this case, the handler property is the actual hook method. This allows you to provide additional optional properties to control the behavior of the hook. See the ObjectHook type for more information.
There are two types of hooks: build hooks and output generation hooks.
Build Hooks
Build hooks are run during the build phase. They are mainly concerned with locating, providing and transforming input files before they are processed by Rolldown.
The first hook of the build phase is options, the last one is always buildEnd. If there is a build error, closeBundle will be called after that.
Note that internalTransform in the graph above is not a plugin hook, it is the step where Rolldown transforms non-JS code to JS.
Additionally, in watch mode the watchChange hook can be triggered at any time to notify a new run will be triggered once the current run has generated its outputs. Also, when watcher closes, the closeWatcher hook will be triggered.
Unsupported Hooks
The following Build Hooks are supported by Rollup, but not by Rolldown:
shouldTransformCachedModule(#4389)
Output Generation Hooks
Output generation hooks can provide information about a generated bundle and modify a build once complete. Plugins that only use output generation hooks can also be passed in via the output options and therefore run only for certain outputs.
The first hook of the output generation phase is renderStart, the last one is either generateBundle if the output was successfully generated via bundle.generate(...), writeBundle if the output was successfully generated via bundle.write(...), or renderError if an error occurred at any time during the output generation.
Additionally, closeBundle can be called as the very last hook, but it is the responsibility of the User to manually call bundle.close() to trigger this. The CLI will always make sure this is the case.
Note that minify in the graph above is not a plugin hook and is the step where Rolldown runs the minifier. Also note that postBanner and postFooter are not plugin hooks, these are output options and do not have corresponding hooks, unlike banner and footer.
Unsupported Hooks
The following Output Generation Hooks are supported by Rollup, but not by Rolldown:
Plugin Context
A number of utility functions and informational bits can be accessed from within most hooks via this. See the PluginContext type for more information.
Notable Differences from Rollup
While Rolldown's plugin interface is largely compatible with Rollup's, there are some important behavioral differences to be aware of:
Output Generation Handling
In Rollup, all outputs are generated together in a single process. However, Rolldown handles each output generation separately. This means that if you have multiple output configurations, Rolldown will process each output independently, which can affect how certain plugins behave, especially those that maintain state across the entire build process.
These are the concrete differences:
outputOptionshook is called before the build hooks in Rolldown, whereas Rollup calls them after the build hooks- Build hooks are called for each output separately, whereas Rollup calls them once for all outputs
closeBundlehook is called only when you calledgenerate()orwrite()at least once, whereas Rollup calls it regardless of whether you calledgenerate()orwrite()
Sequential Hook Execution
In Rollup, certain hooks like writeBundle are "parallel" by default, meaning they run concurrently across multiple plugins. This requires plugins to explicitly set sequential: true if they need their hooks to run one after another.
In Rolldown, the writeBundle hook is already sequential by default, so plugins do not need to specify sequential: true for this hook.