Interface: FunctionPluginHooks
Build Hooks
buildEnd
- Type: (
this,err?) =>void - Kind:
async,parallel
Called when Rolldown has finished bundling, but before Output Generation Hooks. If an error occurred during the build, it is passed on to this hook.
Parameters
this
err?
Error
The error occurred during the build if applicable. Normally BundleError
Returns
void
buildStart
- Type: (
this,options) =>void - Kind:
async,parallel
Called on each rolldown() build.
This is the recommended hook to use when you need access to the options passed to rolldown() as it takes the transformations by all options hooks into account and also contains the right default values for unset options.
Parameters
this
options
Returns
void
closeWatcher
- Type: (
this) =>void - Kind:
async,parallel
Notifies a plugin when the watcher process will close so that all open resources can be closed too.
This hook cannot be used by output plugins.
Parameters
this
Returns
void
load
- Type: (
this,id) =>MaybePromise<undefined|null|string|void|SourceDescription> - Kind:
async,first
Defines a custom loader.
Returning null defers to other load hooks or the built-in loading mechanism.
You can use this.getModuleInfo() to find out the previous values of meta, moduleSideEffects inside this hook.
Parameters
this
id
string
Returns
MaybePromise<undefined | null | string | void | SourceDescription>
moduleParsed
- Type: (
this,moduleInfo) =>void - Kind:
async,parallel
This hook is called each time a module has been fully parsed by Rolldown.
This hook will wait until all imports are resolved so that the information in moduleInfo.importedIds, moduleInfo.dynamicallyImportedIds are complete and accurate. Note however that information about importing modules may be incomplete as additional importers could be discovered later. If you need this information, use the buildEnd hook.
Parameters
this
moduleInfo
Returns
void
onLog
- Type: (
this,level,log) =>boolean|undefined|null|void - Kind:
sync,sequential
A function that receives and filters logs and warnings generated by Rolldown and plugins before they are passed to the onLog option or printed to the console.
If false is returned, the log will be filtered out. Otherwise, the log will be handed to the onLog hook of the next plugin, the onLog option, or printed to the console. Plugins can also change the log level of a log or turn a log into an error by passing the log object to this.error, this.warn, this.info or this.debug and returning false.
Note that unlike other plugin hooks that add e.g. the plugin name to the log, those functions will not add or change properties of the log. Additionally, logs generated by an onLog hook will not be passed back to the onLog hook of the same plugin. If another plugin generates a log in response to such a log in its own onLog hook, this log will not be passed to the original onLog hook, either.
Example
function plugin1() {
return {
name: 'plugin1',
buildStart() {
this.info({ message: 'Hey', pluginCode: 'SPECIAL_CODE' });
},
onLog(level, log) {
if (log.plugin === 'plugin1' && log.pluginCode === 'SPECIAL_CODE') {
// We turn logs into warnings based on their code. This warnings
// will not be passed back to the same plugin to avoid an
// infinite loop, but other plugins will still receive it.
this.warn(log);
return false;
}
},
};
}
function plugin2() {
return {
name: 'plugin2',
onLog(level, log) {
if (log.plugin === 'plugin1' && log.pluginCode === 'SPECIAL_CODE') {
// You can modify logs in this hooks as well
log.meta = 'processed by plugin 2';
// This turns the log back to "info". If this happens in
// response to the first plugin, it will not be passed back to
// either plugin to avoid an infinite loop. If both plugins are
// active, the log will be an info log if the second plugin is
// placed after the first one
this.info(log);
return false;
}
},
};
}Parameters
this
level
"info" | "debug" | "warn"
log
Returns
boolean | undefined | null | void
options
- Type: (
this,options) =>undefined|null|void|InputOptions - Kind:
async,sequential
Replaces or manipulates the options object passed to rolldown().
Returning null does not replace anything.
If you just need to read the options, it is recommended to use the buildStart hook as that hook has access to the options after the transformations from all options hooks have been taken into account.
Parameters
this
options
Returns
undefined | null | void | InputOptions
outputOptions
- Type: (
this,options) =>OutputOptions|undefined|null|void - Kind:
sync,sequential
Replaces or manipulates the output options object passed to bundle.generate() or bundle.write().
Returning null does not replace anything.
If you just need to read the output options, it is recommended to use the renderStart hook as this hook has access to the output options after the transformations from all outputOptions hooks have been taken into account.
Parameters
this
options
Returns
OutputOptions | undefined | null | void
resolveDynamicImport
- Type: (
this,source,importer) =>undefined|null|string|false|void|PartialResolvedId - Kind:
async,first
Defines a custom resolver for dynamic imports.
Parameters
this
source
string
The importee exactly as it is written in the import statement.
For example, given import('./foo.js'), the source will be "./foo.js".
In Rollup, this parameter can also be an AST node. But Rolldown always provides a string.
importer
string | undefined
The fully resolved id of the importing module.
This will be undefined when this.resolve(source, undefined, { kind: 'dynamic-import' )} is called.
Returns
undefined | null | string | false | void | PartialResolvedId
Deprecated
This hook exists only for Rollup compatibility. Please use resolveId instead.
resolveId
- Type: (
this,source,importer,extraOptions) =>undefined|null|string|false|void|PartialResolvedId - Kind:
async,first
Defines a custom resolver.
A resolver can be useful for e.g. locating third-party dependencies.
Returning null defers to other resolveId hooks and eventually the default resolution behavior. Returning false signals that source should be treated as an external module and not included in the bundle. If this happens for a relative import, the id will be renormalized the same way as when the InputOptions.external option is used. If you return an object, then it is possible to resolve an import to a different id while excluding it from the bundle at the same time.
Note that while resolveId will be called for each import of a module and can therefore resolve to the same id many times, values for external, meta or moduleSideEffects can only be set once before the module is loaded. The reason is that after this call, Rolldown will continue with the load and transform hooks for that module that may override these values and should take precedence if they do so.
Parameters
this
source
string
The importee exactly as it is written in the import statement.
For example, given import foo from './foo.js', the source will be "./foo.js".
importer
string | undefined
The fully resolved id of the importing module.
When resolving entry points, importer will usually be undefined. An exception here is entry points generated via this.emitFile as here, you can provide an importer argument. For those cases, the isEntry option will tell you if we are resolving a user defined entry point, an emitted chunk, or if the isEntry parameter was provided for the this.resolve function.
extraOptions
custom?
Plugin-specific options.
See Custom resolver options section for more details.
isEntry
boolean
Whether this is resolution for an entry point.
Define custom proxy modules for entry points
This can be used for instance as a mechanism to define custom proxy modules for entry points. The following plugin will proxy all entry points to inject a polyfill import.
import { exactRegex } from '@rolldown/pluginutils';
// We prefix the polyfill id with \0 to tell other plugins not to try to load or
// transform it
const POLYFILL_ID = '\0polyfill';
const PROXY_SUFFIX = '?inject-polyfill-proxy';
function injectPolyfillPlugin() {
return {
name: 'inject-polyfill',
async resolveId(source, importer, options) {
if (source === POLYFILL_ID) {
// It is important that side effects are always respected for polyfills,
// otherwise using `treeshake.moduleSideEffects: false` may prevent the
// polyfill from being included.
return { id: POLYFILL_ID, moduleSideEffects: true };
}
if (options.isEntry) {
// Determine what the actual entry would have been.
const resolution = await this.resolve(source, importer, options);
// If it cannot be resolved or is external, just return it so that Rolldown
// can display an error
if (!resolution || resolution.external) return resolution;
// In the load hook of the proxy, we need to know if the entry has a
// default export. There, however, we no longer have the full "resolution"
// object that may contain meta-data from other plugins that is only added
// on first load. Therefore we trigger loading here.
const moduleInfo = await this.load(resolution);
// We need to make sure side effects in the original entry point are
// respected even for `treeshake.moduleSideEffects: false`. "moduleSideEffects"
// is a writable property on ModuleInfo.
moduleInfo.moduleSideEffects = true;
// It is important that the new entry does not start with `\0` and has the same
// directory as the original one to not mess up relative external import generation.
// Also keeping the name and just adding a "?query" to the end ensures that
// `preserveModules` will generate the original entry name for this entry.
return `${resolution.id}${PROXY_SUFFIX}`;
}
return null;
},
load: {
filter: { id: [exactRegex(POLYFILL_ID), /\?proxy$/] },
handler(id) {
if (id === POLYFILL_ID) {
// Replace with actual polyfill
return "console.log('polyfill');";
}
if (id.endsWith(PROXY_SUFFIX)) {
const entryId = id.slice(0, -PROXY_SUFFIX.length);
// We know ModuleInfo.exports is reliable because we awaited this.load in resolveId
const { exports } = this.getModuleInfo(entryId);
let code =
`import ${JSON.stringify(POLYFILL_ID)};` + `export * from ${JSON.stringify(entryId)};`;
// Namespace reexports do not reexport default, so we need special handling here
if (exports.includes('default')) {
code += `export { default } from ${JSON.stringify(entryId)};`;
}
return code;
}
return null;
},
},
};
}kind
"import-statement" | "dynamic-import" | "require-call" | "import-rule" | "url-token" | "new-url" | "hot-accept"
The kind of import being resolved.
import-statement:import { foo } from './lib.js';dynamic-import:import('./lib.js')require-call:require('./lib.js')import-rule:@import 'bg-color.css'(experimental)url-token:url('./icon.png')(experimental)new-url:new URL('./worker.js', import.meta.url)(experimental)hot-accept:import.meta.hot.accept('./lib.js', () => {})(experimental)
Returns
undefined | null | string | false | void | PartialResolvedId
transform
- Type: (
this,code,id,meta) =>undefined|null|string|void|Omit<SourceDescription,"code"> & {code?:string|RolldownMagicString; } - Kind:
async,sequential
Can be used to transform individual modules.
Note that it's possible to return only properties and no code transformations.
You can use this.getModuleInfo() to find out the previous values of meta, moduleSideEffects inside this hook.
Changing moduleType
When you change the type of the module by returning moduleType property, the module is not thrown back to the beginning of the plugin chain. This means the transform hooks of the plugins that already saw this module will not be called with the new moduleType. For this reason, it is recommended to place the plugins that change the moduleType at the beginning of the plugin list.
If you need to let all the plugins be called, you can create a virtual module with a different moduleType instead of changing the moduleType directly in the transform hook.
Parameters
this
code
string
id
string
meta
BindingTransformHookExtraArgs & { ast?: Program; magicString?: RolldownMagicString; moduleType: ModuleType; }
Returns
undefined | null | string | void | Omit<SourceDescription, "code"> & { code?: string | RolldownMagicString; }
watchChange
- Type: (
this,id,event) =>void - Kind:
async,parallel
Notifies a plugin whenever Rolldown has detected a change to a monitored file in watch mode.
If a build is currently running, this hook is called once the build finished. It will be called once for every file that changed.
This hook cannot be used by output plugins.
If you need to be notified immediately when a file changed, you can use the watch.onInvalidate option.
Parameters
this
id
string
event
event
ChangeEvent
Returns
void
Output Generation Hooks
augmentChunkHash
- Type: (
this,chunk) =>string|void - Kind:
sync,sequential
Can be used to augment the hash of individual chunks. Called for each Rolldown output chunk.
Returning a falsy value will not modify the hash. Truthy values will be used as an additional source for hash calculation.
Example
The following plugin will invalidate the hash of chunk foo with the current timestamp:
function augmentWithDatePlugin() {
return {
name: 'augment-with-date',
augmentChunkHash(chunkInfo) {
if (chunkInfo.name === 'foo') {
return Date.now().toString();
}
},
};
}Parameters
this
chunk
Returns
string | void
closeBundle
- Type: (
this,error?) =>void - Kind:
async,parallel
Can be used to clean up any external service that may be running.
Rolldown's CLI will make sure this hook is called after each run, but it is the responsibility of users of the JavaScript API to manually call bundle.close() once they are done generating bundles. For that reason, any plugin relying on this feature should carefully mention this in its documentation.
If a plugin wants to retain resources across builds in watch mode, they can check for this.meta.watchMode in this hook and perform the necessary cleanup for watch mode in closeWatcher.
Parameters
this
error?
Error
An error that occurred during build or the buildEnd hook, if any.
Returns
void
generateBundle
- Type: (
this,outputOptions,bundle,isWrite) =>void - Kind:
async,sequential
Called at the end of bundle.generate() or immediately before the files are written in bundle.write().
To modify the files after they have been written, use the writeBundle hook.
You can prevent files from being emitted by deleting them from the bundle object in this hook. To emit additional files, use the this.emitFile function.
DANGER
Do not directly add assets to the bundle. This will not work as expected as Rolldown will ignore those assets. This is not recommended in Rollup as well.
Instead, always use this.emitFile.
Parameters
this
outputOptions
bundle
Provides the full list of files being written or generated along with their details.
isWrite
boolean
Returns
void
renderChunk
- Type: (
this,code,chunk,outputOptions,meta) =>string|RolldownMagicString|undefined|null|void| {code:string|RolldownMagicString;map?: SourceMapInput | undefined; } - Kind:
async,sequential
Can be used to transform individual chunks. Called for each Rolldown output chunk file.
Returning null will apply no transformations. If you change code in this hook and want to support source maps, you need to return a map describing your changes, see Source Code Transformations section.
chunk is mutable and changes applied in this hook will propagate to other plugins and to the generated bundle. That means if you add or remove imports or exports in this hook, you should update imports, RenderedChunk.importedBindings | importedBindings and/or exports accordingly.
Parameters
this
code
string
chunk
outputOptions
meta
RenderedChunkMeta
Returns
string | RolldownMagicString | undefined | null | void | { code: string | RolldownMagicString; map?: SourceMapInput | undefined; }
renderError
- Type: (
this,error) =>void - Kind:
async,parallel
Called when Rolldown encounters an error during bundle.generate() or bundle.write().
To get notified when generation completes successfully, use the generateBundle hook.
Parameters
this
error
Error
The error that occurred during the build. Normally BundleError
Returns
void
renderStart
- Type: (
this,outputOptions,inputOptions) =>void - Kind:
async,parallel
Called initially each time bundle.generate() or bundle.write() is called.
To get notified when generation has completed, use the generateBundle and renderError hooks.
This is the recommended hook to use when you need access to the output options passed to bundle.generate() or bundle.write() as it takes the transformations by all outputOptions hooks into account and also contains the right default values for unset options.
It also receives the input options passed to rolldown() so that plugins that can be used as output plugins, i.e. plugins that only use generate phase hooks, can get access to them.
Parameters
this
outputOptions
inputOptions
Returns
void
resolveFileUrl
- Type: (
this,args) =>string|undefined|null|void
Allows customizing how Rolldown resolves URLs of files that were emitted by plugins via this.emitFile. By default, Rolldown will generate code for import.meta.ROLLDOWN_FILE_URL_referenceId that resolves the emitted file relative to import.meta.url. This generates correct absolute URLs for the esm format, and for the cjs format on the node platform where import.meta.url is polyfilled. For the iife and umd formats, import.meta.url is not available and the generated code will not work — Rolldown emits a warning in that case. To support these formats, this hook needs to be implemented to return code that does not rely on import.meta.url. See File URLs for more details and an example.
This hook can be used to customize the behavior of import.meta.ROLLDOWN_FILE_URL_referenceId.
The returned string must be a single JavaScript expression. Also the returned expression must be side-effect free. If the URL is not used in the code, Rolldown will remove it.
Rolldown additionally accepts import.meta.ROLLDOWN_FILE_URL_referenceId_urlId, where urlId is an arbitrary identifier of your choosing. It is passed to this hook as args.urlId, letting a single plugin resolve the same emitted file differently depending on the reference. The urlId API is experimental and may change in minor versions. The urlId is not available on the Rollup-compatible ROLLUP_FILE_URL_ alias. Use only ASCII identifier characters in a urlId: letters, digits, _, and $.
import.meta.url in the returned string
If the returned string contains import.meta.url, it will be rewritten for non-ESM formats similarly to when import.meta.url is used in the code directly. Unlike Rolldown, Rollup outputs import.meta.url as-is.
Example
The following plugin will always resolve all files relative to the current document:
function resolveToDocumentPlugin() {
return {
name: 'resolve-to-document',
resolveFileUrl({ fileName }) {
return `new URL(${JSON.stringify(fileName)}, document.baseURI).href`;
},
};
}Parameters
this
args
Returns
string | undefined | null | void
writeBundle
- Type: (
this,outputOptions,bundle) =>void - Kind:
async,parallel
Called only at the end of bundle.write() once all files have been written.
Parameters
this
outputOptions
bundle
Provides the full list of files being written or generated along with their details.
Returns
void