Skip to content

Interface: PluginContext

Extends

Extended by

Properties

fs

Provides abstract access to the file system.


meta

An object containing potentially useful metadata.

Inherited from

MinimalPluginContext.meta

Methods

getModuleInfo()

Get additional information about the module in question.

During the build, this object represents currently available information about the module which may be inaccurate before the buildEnd hook:

  • id will never change.
  • code, exports are only available after parsing, i.e. in the moduleParsed hook or after awaiting this.load. At that point, they will no longer change.
  • isEntry is true, it will no longer change. It is however possible for modules to become entry points after they are parsed, either via this.emitFile or because a plugin inspects a potential entry point via this.load in the resolveId hook when resolving an entry point. Therefore, it is not recommended relying on this flag in the transform hook. It will no longer change after buildEnd.
  • importers and dynamicImporters will start as empty arrays, which receive additional entries as new importers and are discovered. They will no longer change after buildEnd.
  • importedIds and dynamicallyImportedIds are available when a module has been parsed and its dependencies have been resolved. This is the case in the moduleParsed hook or after awaiting this.load with the resolveDependencies flag. At that point, they will no longer change.
  • meta and moduleSideEffects can be changed by load and transform hooks. Moreover, while most properties are read-only, these properties are writable and changes will be picked up if they occur before the buildEnd hook is triggered. meta itself should not be overwritten, but it is ok to mutate its properties at any time to store meta information about a module. The advantage of doing this instead of keeping state in a plugin is that meta is persisted to and restored from the cache if it is used, e.g. when using watch mode from the CLI.

Parameters

moduleId

string

Returns

ModuleInfo | null

Module information for that module. null if the module could not be found.


addWatchFile()

  • Type: (id: string) => void

Adds additional files to be monitored in watch mode so that changes to these files will trigger rebuilds.

Note that when emitting assets that correspond to an existing file, it is recommended to set the originalFileName property in the this.emitFile call instead as that will not only watch the file but also make the connection transparent to other plugins.

Note: Usually in watch mode to improve rebuild speed, the transform hook will only be triggered for a given module if its contents actually changed. Using this.addWatchFile from within the transform hook will make sure the transform hook is also reevaluated for this module if the watched file changes.

In general, it is recommended to use this.addWatchFile from within the hook that depends on the watched file.

Parameters

id

string

The path to be monitored.

This can be an absolute path to a file or directory or a path relative to the current working directory.

Returns

void


emitFile()

Emits a new file that is included in the build output. You can emit chunks, prebuilt chunks or assets.

In-depth (type: 'chunk')

If the type is 'chunk', this emits a new chunk with the given module id as entry point. This will not result in duplicate modules in the graph, instead if necessary, existing chunks will be split or a facade chunk with reexports will be created. Chunks with a specified fileName will always generate separate chunks while other emitted chunks may be deduplicated with existing chunks even if the name does not match. If such a chunk is not deduplicated, the output.chunkFileNames pattern will be used.

You can reference the URL of an emitted file in any code returned by a load or transform plugin hook via import.meta.ROLLUP_FILE_URL_referenceId (returns a string). See File URLs for more details and an example.

You can use this.getFileName(referenceId) to determine the file name as soon as it is available. If the file name is not set explicitly, then:

  • asset file names are available starting with the renderStart hook. For assets that are emitted later, the file name will be available immediately after emitting the asset.
  • chunk file names that do not contain a hash are available as soon as chunks are created after the renderStart hook.
  • if a chunk file name would contain a hash, using getFileName in any hook before generateBundle will return a name containing a placeholder instead of the actual name. If you use this file name or parts of it in a chunk you transform in renderChunk, Rolldown will replace the placeholder with the actual hash before generateBundle, making sure the hash reflects the actual content of the final generated chunk including all referenced file hashes.

In-depth (type: 'prebuilt-chunk')

If the type is 'prebuilt-chunk', this emits a chunk with fixed contents provided by the code property.

To reference a prebuilt chunk in imports, we need to mark the "module" as external in the resolveId hook as prebuilt chunks are not part of the module graph. Instead, they behave like assets with chunk meta-data:

js
function emitPrebuiltChunkPlugin() {
  return {
    name: 'emit-prebuilt-chunk',
    resolveId: {
      filter: { id: /^\.\/my-prebuilt-chunk\.js$/ },
      handler(source) {
        return {
          id: source,
          external: true,
        };
      },
    },
    buildStart() {
      this.emitFile({
        type: 'prebuilt-chunk',
        fileName: 'my-prebuilt-chunk.js',
        code: 'export const foo = "foo"',
        exports: ['foo'],
      });
    },
  };
}

Then you can reference the prebuilt chunk in your code by import { foo } from './my-prebuilt-chunk.js';.

In-depth (type: 'asset')

If the type is 'asset', this emits an arbitrary new file with the given source as content. Assets with a specified fileName will always generate separate files while other emitted assets may be deduplicated with existing assets if they have the same source even if the name does not match. If an asset without a fileName is not deduplicated, the output.assetFileNames pattern will be used.

Parameters

file

EmittedAsset | EmittedChunk | EmittedPrebuiltChunk

Returns

string

A referenceId for the emitted file that can be used in various places to reference the emitted file.


getFileName()

  • Type: (referenceId: string) => string

Get the file name of a chunk or asset that has been emitted via this.emitFile.

Parameters

referenceId

string

Returns

string

The file name of the emitted file. Relative to output.dir.


getModuleIds()

  • Type: () => IterableIterator<string>

Get all module ids in the current module graph.

Returns

IterableIterator<string>

An iterator of module ids. It can be iterated via

js
for (const moduleId of this.getModuleIds()) {
  // ...
}

or converted into an array via Array.from(this.getModuleIds()).


load()

Loads and parses the module corresponding to the given id, attaching additional meta information to the module if provided. This will trigger the same load, transform and moduleParsed hooks as if the module was imported by another module.

This allows you to inspect the final content of modules before deciding how to resolve them in the resolveId hook and e.g. resolve to a proxy module instead. If the module becomes part of the graph later, there is no additional overhead from using this context function as the module will not be parsed again. The signature allows you to directly pass the return value of this.resolve to this function as long as it is neither null nor external.

The returned Promise will resolve once the module has been fully transformed and parsed but before any imports have been resolved. That means that the resulting ModuleInfo will have empty importedIds and dynamicallyImportedIds. This helps to avoid deadlock situations when awaiting this.load in a resolveId hook. If you are interested in importedIds and dynamicallyImportedIds, you can either implement a moduleParsed hook or pass the resolveDependencies flag, which will make the Promise returned by this.load wait until all dependency ids have been resolved.

Note that with regard to the meta and moduleSideEffects options, the same restrictions apply as for the resolveId hook: Their values only have an effect if the module has not been loaded yet. Thus, it is very important to use this.resolve first to find out if any plugins want to set special values for these options in their resolveId hook, and pass these options on to this.load if appropriate. The example below showcases how this can be handled to add a proxy module for modules containing a special code comment. Note the special handling for re-exporting the default export:

js
export default function addProxyPlugin() {
  return {
    async resolveId(source, importer, options) {
      if (importer?.endsWith('?proxy')) {
        // Do not proxy ids used in proxies
        return null;
      }
      // We make sure to pass on any resolveId options to
      // this.resolve to get the module id
      const resolution = await this.resolve(source, importer, options);
      // We can only pre-load existing and non-external ids
      if (resolution && !resolution.external) {
        // we pass on the entire resolution information
        const moduleInfo = await this.load(resolution);
        if (moduleInfo.code.includes('/* use proxy */')) {
          return `${resolution.id}?proxy`;
        }
      }
      // As we already fully resolved the module, there is no reason
      // to resolve it again
      return resolution;
    },
    load: {
      filter: { id: /\?proxy$/ },
      handler(id) {
        const importee = id.slice(0, -'?proxy'.length);
        // Note that namespace reexports do not reexport default exports
        let code =
          `console.log('proxy for ${importee}'); ` + `export * from ${JSON.stringify(importee)};`;
        // We know that while resolving the proxy, importee was
        // already fully loaded and parsed, so we can rely on `exports`
        if (this.getModuleInfo(importee).exports.includes('default')) {
          code += `export { default } from ${JSON.stringify(importee)};`;
        }
        return code;
      },
    },
  };
}

If the module was already loaded, this.load will just wait for the parsing to complete and then return its module information. If the module was not yet imported by another module, it will not automatically trigger loading other modules imported by this module. Instead, static and dynamic dependencies will only be loaded once this module has actually been imported at least once.

Deadlocks caused by awaiting this.load in cyclic dependencies

While it is safe to use this.load in a resolveId hook, you should be very careful when awaiting it in a load or transform hook. If there are cyclic dependencies in the module graph, this can easily lead to a deadlock, so any plugin needs to manually take care to avoid waiting for this.load inside the load or transform of the any module that is in a cycle with the loaded module.

Parameters

options

{ id: string; resolveDependencies?: boolean; } & Partial<PartialNull<ModuleOptions>>

Returns

Promise<ModuleInfo>


parse()

  • Type: (input: string, options?: ParserOptions | null) => Program

Use Rolldown's internal parser to parse code to an ESTree-compatible AST.

Parameters

input

string

options?

ParserOptions | null

Returns

Program


resolve()

Resolve imports to module ids (i.e. file names) using the same plugins that Rolldown uses, and determine if an import should be external.

When calling this function from a resolveId hook, you should always check if it makes sense for you to pass along the options.

Parameters

source

string

importer?

string

options?

PluginContextResolveOptions

Returns

Promise<ResolvedId | null>

If Promise<null> is returned, the import could not be resolved by Rolldown or any plugin but was not explicitly marked as external by the user. If an absolute external id is returned that should remain absolute in the output either via the makeAbsoluteExternalsRelative option or by explicit plugin choice in the resolveId hook, external will be "absolute" instead of true.

Logging Methods

debug()

  • Type: (log) => void

Generate a "debug" level log.

code will be set to "PLUGIN_LOG" by Rolldown. Make sure to add a distinctive pluginCode to those logs for easy filtering.

These logs are only processed if the logLevel option is explicitly set to "debug", otherwise it does nothing. Therefore, it is encouraged to add helpful debug logs to plugins as that can help spot issues while they will be efficiently muted by default.

Lazily Compute

If you need to do expensive computations to generate the log, make sure to use the function form so that these computations are only performed if the log is actually processed.

js
function plugin() {
  return {
    name: 'test',
    transform(code, id) {
      this.debug(
        () => `transforming ${id},\n` + `module contains, ${code.split('\n').length} lines`,
      );
    },
  };
}

Parameters

log

The log object or message.

The string argument is equivalent to passing an object with only the message property.

string | RolldownLog | () => string | RolldownLog

Returns

void

Inherited from

MinimalPluginContext.debug


error()

  • Type: (e) => never

Similar to this.warn, except that it will also abort the bundling process with an error.

If an Error instance is passed, it will be used as-is, otherwise a new Error instance will be created with the given error message and all additional provided properties.

In all hooks except the onLog hook, the error will be augmented with code: "PLUGIN_ERROR" and plugin: plugin.name properties. If a code property already exists and the code does not start with PLUGIN_, it will be renamed to pluginCode.

Parameters

e

string | RolldownError

Returns

never

Inherited from

MinimalPluginContext.error


info()

  • Type: (log) => void

Generate a "info" level log.

code will be set to "PLUGIN_LOG" by Rolldown. As these logs are displayed by default, use them for information that is not a warning but makes sense to display to all users on every build.

If the logLevel option is set to "warn" or "silent", this method will do nothing.

Parameters

log

The log object or message.

The string argument is equivalent to passing an object with only the message property.

string | RolldownLog | () => string | RolldownLog

Returns

void

Inherited from

MinimalPluginContext.info


warn()

  • Type: (log) => void

Generate a "warn" level log.

Just like internally generated warnings, these logs will be first passed to and filtered by plugin onLog hooks before they are forwarded to custom onLog or onwarn handlers or printed to the console.

We encourage you to use objects with a pluginCode property as that will allow users to easily filter for those logs in an onLog handler.

If you need to add additional information, you can use the meta property. If the log contains a code and does not yet have a pluginCode property, it will be renamed to pluginCode as plugin warnings always get a code of PLUGIN_WARNING added by Rolldown.

If the logLevel option is set to "silent", this method will do nothing.

Lazily Compute

If you need to do expensive computations to generate the log, make sure to use the function form so that these computations are only performed if the log is actually processed.

Parameters

log

The log object or message.

The string argument is equivalent to passing an object with only the message property.

string | RolldownLog | () => string | RolldownLog

Returns

void

Inherited from

MinimalPluginContext.warn