---
url: /reference/Interface.Plugin.md
---
# Interface: Plugin\<A>

The Plugin interface.

See [Plugin API document](/apis/plugin-api) for details.

## Extends

* `OutputPlugin`.`Partial`<`PluginHooks`>

## Type Parameters

### A

`A` = `any`

The type of the [api](#api) property.

## Properties

### api?

* **Type**: `A`
* **Optional**

Used for inter-plugin communication.

***

### meta?

* **Type**: [`PluginMeta`](Interface.PluginMeta.md)
* **Optional**
* **Experimental**

Descriptive metadata about the plugin, such as the npm package it ships in.

This does not affect bundling; it is informational and intended to be
surfaced by tooling that inspects a build. See [`PluginMeta`](Interface.PluginMeta.md).

#### Inherited from

`OutputPlugin.meta`

***

### name

* **Type**: `string`

The name of the plugin, for use in error messages and logs.

#### Inherited from

`OutputPlugin.name`

***

### version?

* **Type**: `string`
* **Optional**

The version of the plugin, for use in inter-plugin communication scenarios.

#### Inherited from

`OutputPlugin.version`

## Build Hooks

### buildEnd?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

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.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`buildEnd`](Interface.FunctionPluginHooks.md#buildend)

***

### buildStart?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

Called on each [`rolldown()`](Function.rolldown.md) build.

This is the recommended hook to use when you need access to the options passed to [`rolldown()`](Function.rolldown.md) as it takes the transformations by all options hooks into account and also contains the right default values for unset options.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`buildStart`](Interface.FunctionPluginHooks.md#buildstart)

***

### closeWatcher?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

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.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`closeWatcher`](Interface.FunctionPluginHooks.md#closewatcher)

***

### load?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => MaybePromise\<LoadResult> | Promise\<MaybePromise\<LoadResult>>, { `filter?`: [`TopLevelFilterExpression`](TypeAlias.TopLevelFilterExpression.md)\[] | `Pick`<[`HookFilter`](Interface.HookFilter.md), `"id"`>; }>
* **Kind**: `async`, `first`
* **Optional**

Defines a custom loader.

Returning `null` defers to other `load` hooks or the built-in loading mechanism.

You can use [`this.getModuleInfo()`](Interface.PluginContext.md#getmoduleinfo) to find out the previous values of `meta`, `moduleSideEffects` inside this hook.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`load`](Interface.FunctionPluginHooks.md#load)

***

### moduleParsed?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

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`](Interface.ModuleInfo.md#importedids),
[`moduleInfo.dynamicallyImportedIds`](Interface.ModuleInfo.md#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`](Interface.FunctionPluginHooks.md#buildend) hook.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`moduleParsed`](Interface.FunctionPluginHooks.md#moduleparsed)

***

### onLog?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, `level`, `log`) => boolean | NullValue, { }>
* **Kind**: `sync`, `sequential`
* **Optional**

A function that receives and filters logs and warnings generated by Rolldown and
plugins before they are passed to the [`onLog`](Interface.InputOptions.md#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`](Interface.InputOptions.md#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`](Interface.MinimalPluginContext.md#error),
[`this.warn`](Interface.MinimalPluginContext.md#warn),
[`this.info`](Interface.MinimalPluginContext.md#info) or
[`this.debug`](Interface.MinimalPluginContext.md#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

```js
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;
      }
    },
  };
}
```

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`onLog`](Interface.FunctionPluginHooks.md#onlog)

***

### options?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => NullValue | InputOptions | Promise\<NullValue | InputOptions>, { }>
* **Kind**: `async`, `sequential`
* **Optional**

Replaces or manipulates the options object passed to [`rolldown()`](Function.rolldown.md).

Returning `null` does not replace anything.

If you just need to read the options, it is recommended to use
the [`buildStart`](Interface.FunctionPluginHooks.md#buildstart) hook as that hook has access to the options
after the transformations from all `options` hooks have been taken into account.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`options`](Interface.FunctionPluginHooks.md#options)

***

### outputOptions?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, `options`) => OutputOptions | NullValue, { }>
* **Kind**: `sync`, `sequential`
* **Optional**

Replaces or manipulates the output options object passed to
[`bundle.generate()`](Interface.RolldownBuild.md#generate) or
[`bundle.write()`](Interface.RolldownBuild.md#write).

Returning null does not replace anything.

If you just need to read the output options, it is recommended to use
the [`renderStart`](Interface.FunctionPluginHooks.md#renderstart) hook as this hook has access to the output options
after the transformations from all `outputOptions` hooks have been taken into account.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`outputOptions`](Interface.FunctionPluginHooks.md#outputoptions)

***

### ~~resolveDynamicImport?~~

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => ResolveIdResult | Promise\<ResolveIdResult>, { }>
* **Kind**: `async`, `first`
* **Optional**

Defines a custom resolver for dynamic imports.

#### Deprecated

This hook exists only for Rollup compatibility. Please use [`resolveId`](Interface.FunctionPluginHooks.md#resolveid) instead.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`resolveDynamicImport`](Interface.FunctionPluginHooks.md#resolvedynamicimport)

***

### resolveId?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => ResolveIdResult | Promise\<ResolveIdResult>, { `filter?`: [`TopLevelFilterExpression`](TypeAlias.TopLevelFilterExpression.md)\[] | { `id?`: GeneralHookFilter\<RegExp> | undefined; }; }>
* **Kind**: `async`, `first`
* **Optional**

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`](Interface.InputOptions.md#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`](Interface.FunctionPluginHooks.md#load) and [`transform`](Interface.FunctionPluginHooks.md#transform) hooks for that
module that may override these values and should take precedence if they do so.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`resolveId`](Interface.FunctionPluginHooks.md#resolveid)

***

### transform?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => TransformResult | Promise\<TransformResult>, { `filter?`: [`HookFilter`](Interface.HookFilter.md) | [`TopLevelFilterExpression`](TypeAlias.TopLevelFilterExpression.md)\[]; }>
* **Kind**: `async`, `sequential`
* **Optional**

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()`](Interface.PluginContext.md#getmoduleinfo) to find out the previous values of `meta`, `moduleSideEffects` inside this hook.

::: warning Changing `moduleType`

When you change the [type of the module](/in-depth/module-types) by returning [`moduleType`](/reference/Interface.SourceDescription#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](/apis/plugin-api#virtual-modules) with a different `moduleType` instead of changing the `moduleType` directly in the `transform` hook.

:::

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`transform`](Interface.FunctionPluginHooks.md#transform)

***

### watchChange?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

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`](Interface.WatcherOptions.md#oninvalidate) option.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`watchChange`](Interface.FunctionPluginHooks.md#watchchange)

## Output Generation Hooks

### augmentChunkHash?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, `chunk`) => `string` | `void`, { }>
* **Kind**: `sync`, `sequential`
* **Optional**

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:

```js
function augmentWithDatePlugin() {
  return {
    name: 'augment-with-date',
    augmentChunkHash(chunkInfo) {
      if (chunkInfo.name === 'foo') {
        return Date.now().toString();
      }
    },
  };
}
```

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`augmentChunkHash`](Interface.FunctionPluginHooks.md#augmentchunkhash)

***

### banner?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<`AddonHook`, { }>
* **Kind**: `async`, `sequential`
* **Optional**

A hook equivalent to [`output.banner`](Interface.OutputOptions.md#banner) option.

#### Inherited from

`OutputPlugin.banner`

***

### closeBundle?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

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()`](Interface.RolldownBuild.md#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`](Interface.PluginContextMeta.md#watchmode) in this hook and perform
the necessary cleanup for watch mode in closeWatcher.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`closeBundle`](Interface.FunctionPluginHooks.md#closebundle)

***

### footer?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<`AddonHook`, { }>
* **Kind**: `async`, `sequential`
* **Optional**

A hook equivalent to [`output.footer`](Interface.OutputOptions.md#footer) option.

#### Inherited from

`OutputPlugin.footer`

***

### generateBundle?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { }>
* **Kind**: `async`, `sequential`
* **Optional**

Called at the end of [`bundle.generate()`](Interface.RolldownBuild.md#generate) or
immediately before the files are written in
[`bundle.write()`](Interface.RolldownBuild.md#write).

To modify the files after they have been written, use the [`writeBundle`](Interface.FunctionPluginHooks.md#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`](/reference/Interface.PluginContext#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](https://rollupjs.org/plugin-development/#generatebundle) as well.

Instead, always use [`this.emitFile`](/reference/Interface.PluginContext#emitfile).

:::

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`generateBundle`](Interface.FunctionPluginHooks.md#generatebundle)

***

### intro?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<`AddonHook`, { }>
* **Kind**: `async`, `sequential`
* **Optional**

A hook equivalent to [`output.intro`](Interface.OutputOptions.md#intro) option.

#### Inherited from

`OutputPlugin.intro`

***

### outro?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<`AddonHook`, { }>
* **Kind**: `async`, `sequential`
* **Optional**

A hook equivalent to [`output.outro`](Interface.OutputOptions.md#outro) option.

#### Inherited from

`OutputPlugin.outro`

***

### renderChunk?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => string | RolldownMagicString | NullValue | { code: string | RolldownMagicString; map?: SourceMapInput | undefined; } | Promise<...>, { `filter?`: [`TopLevelFilterExpression`](TypeAlias.TopLevelFilterExpression.md)\[] | `Pick`<[`HookFilter`](Interface.HookFilter.md), `"code"`>; }>
* **Kind**: `async`, `sequential`
* **Optional**

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](/apis/plugin-api/transformations#source-code-transformations).

`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`](Interface.RenderedChunk.md#imports), RenderedChunk.importedBindings | importedBindings and/or [`exports`](Interface.RenderedChunk.md#exports) accordingly.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`renderChunk`](Interface.FunctionPluginHooks.md#renderchunk)

***

### renderError?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

Called when Rolldown encounters an error during
[`bundle.generate()`](Interface.RolldownBuild.md#generate) or
[`bundle.write()`](Interface.RolldownBuild.md#write).

To get notified when generation completes successfully, use the
[`generateBundle`](Interface.FunctionPluginHooks.md#generatebundle) hook.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`renderError`](Interface.FunctionPluginHooks.md#rendererror)

***

### renderStart?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

Called initially each time [`bundle.generate()`](Interface.RolldownBuild.md#generate) or
[`bundle.write()`](Interface.RolldownBuild.md#write) is called.

To get notified when generation has completed, use the [`generateBundle`](Interface.FunctionPluginHooks.md#generatebundle) and
[`renderError`](Interface.FunctionPluginHooks.md#rendererror) hooks.

This is the recommended hook to use when you need access to the output options passed to
[`bundle.generate()`](Interface.RolldownBuild.md#generate) or
[`bundle.write()`](Interface.RolldownBuild.md#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()`](Function.rolldown.md) so that
plugins that can be used as output plugins, i.e. plugins that only use generate phase hooks,
can get access to them.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`renderStart`](Interface.FunctionPluginHooks.md#renderstart)

***

### resolveFileUrl?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, `args`) => string | NullValue, { }>
* **Optional**

Allows customizing how Rolldown resolves URLs of files that were emitted by plugins via [`this.emitFile`](/reference/Interface.PluginContext#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](/in-depth/non-esm-output-formats#well-known-import-meta-properties). 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](/apis/plugin-api/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 `$`.

::: tip `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](/in-depth/non-esm-output-formats#well-known-import-meta-properties). Unlike Rolldown, Rollup outputs `import.meta.url` as-is.

:::

#### Example

The following plugin will always resolve all files relative to the current document:

```js
function resolveToDocumentPlugin() {
  return {
    name: 'resolve-to-document',
    resolveFileUrl({ fileName }) {
      return `new URL(${JSON.stringify(fileName)}, document.baseURI).href`;
    },
  };
}
```

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`resolveFileUrl`](Interface.FunctionPluginHooks.md#resolvefileurl)

***

### writeBundle?

* **Type**: [`ObjectHook`](TypeAlias.ObjectHook.md)<(`this`, ...`parameters`) => `void` | `Promise`<`void`>, { `sequential?`: `boolean`; }>
* **Kind**: `async`, `parallel`
* **Optional**

Called only at the end of [`bundle.write()`](Interface.RolldownBuild.md#write) once
all files have been written.

#### Inherited from

[`FunctionPluginHooks`](Interface.FunctionPluginHooks.md).[`writeBundle`](Interface.FunctionPluginHooks.md#writebundle)
