> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Compiler hooks

Compiler hooks allow Rspack plugins to intervene at specific stages of the build process. These hooks represent various lifecycle stages from initialization to asset output.

This document lists the available compiler hooks in Rspack, their trigger timing, parameters, and usage examples.

:::tip
See [Compiler](/api/javascript-api/compiler.md) for more information about the Compiler object.
:::

## Overview


## `environment`

Called while preparing the compiler environment, right after initializing the plugins in the configuration file.

- **Type:** `SyncHook<[]>`

## `afterEnvironment`

Called right after the `environment` hook, when the compiler environment setup is complete.

- **Type:** `SyncHook<[]>`

## `entryOption`

Called after the [`entry`](/config/entry.md) configuration from Rspack options has been processed.

- **Type:** `SyncBailHook<[string, EntryNormalized]>`
- **Arguments:**
  - `string`: same with [`context`](/config/context.md)
  - `EntryNormalized`: normalized [`entry`](/config/entry.md)

## `afterPlugins`

Called after setting up initial set of internal plugins.

- **Type:** `SyncHook<[Compiler]>`
- **Arguments:**
  - `Compiler`: current compiler instance


Compiler.ts

## `afterResolvers`

Triggered after resolver setup is complete.

- **Type:** `SyncHook<[Compiler]>`
- **Arguments:**
  - `Compiler`: current compiler instance


Compiler.ts

## `initialize`

Called when a compiler object is initialized.

- **Type:** `SyncHook<[]>`

## `beforeRun`

Adds a hook right before running the compiler.

:::note

This hook is only triggered when calling [compiler.run()](/api/javascript-api/index.md#compilerrun) (which is used by the `rspack build` command), and will not be executed in watch mode. You can use the [watchRun](#watchrun) hook in watch mode.

:::

- **Type:** `AsyncSeriesHook<[Compiler]>`
- **Arguments:**
  - `Compiler`: current compiler instance


Compiler.ts

- **Example:** Sync operation

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.beforeRun.tap('ExamplePlugin', (compiler) => {
      console.log('Build is about to start...');
    });
  }
}
```

- **Example:** Async operation

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.beforeRun.tapPromise('ExamplePlugin', async (compiler) => {
      console.log('Build is about to start...');

      await someAsyncOperation();
    });
  }
}
```

## `run`

Called at the beginning of a build execution.

:::note

This hook is only triggered when calling [compiler.run()](/api/javascript-api/index.md#compilerrun) (which is used by the `rspack build` command), and will not be executed in watch mode. You can use the [watchRun](#watchrun) hook in watch mode.

:::

- **Type:** `AsyncSeriesHook<[Compiler]>`
- **Arguments:**
  - `Compiler`: current compiler instance


Compiler.ts

- **Example:** Sync operation

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.run.tap('ExamplePlugin', (compiler) => {
      console.log('Build start...');
    });
  }
}
```

- **Example:** Async operation

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.run.tapPromise('ExamplePlugin', async (compiler) => {
      console.log('Build start...');

      await someAsyncOperation();
    });
  }
}
```

## `watchRun`

Executes a plugin during watch mode after a new compilation is triggered but before the compilation is actually started.

You can use `compiler.modifiedFiles` and `compiler.removedFiles` to get the changed file paths and removed file paths.

:::note

This hook is only triggered when calling [compiler.watch()](/api/javascript-api/index.md#compilerwatch), and will not be called in non-watch mode. You can use the [run](#run) or [beforeRun](#beforerun) hook in non-watch mode.

:::

- **Type:** `AsyncSeriesHook<[Compiler]>`
- **Arguments:**
  - `Compiler`: current compiler instance


Compiler.ts

- **Example:** Sync operation

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.watchRun.tap('ExamplePlugin', (compiler) => {
      const { modifiedFiles, removedFiles } = compiler;
      if (modifiedFiles) {
        console.log('Changed files:', Array.from(modifiedFiles));
      }
      if (removedFiles) {
        console.log('Removed files:', Array.from(removedFiles));
      }
    });
  }
}
```

- **Example:** Async operation

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.watchRun.tapPromise('ExamplePlugin', async (compiler) => {
      await someAsyncOperation();
    });
  }
}
```

## `beforeCompile`

Executes a plugin after compilation parameters are created.

- **Type:** `AsyncSeriesHook<[CompilationParams]>`
- **Arguments:**
  - `params`: compilation parameters containing the [normal module factory](/api/plugin-api/normal-module-factory-hooks.md) and [context module factory](/api/plugin-api/context-module-factory-hooks.md).

```ts
type CompilationParams = {
  normalModuleFactory: NormalModuleFactory;
  contextModuleFactory: ContextModuleFactory;
};
```

## `compile`

Called right after `beforeCompile`, before a new [compilation object](/api/javascript-api/compilation.md) is created.

- **Type:** `SyncHook<[CompilationParams]>`
- **Arguments:**
  - `params`: the same compilation parameters passed to [beforeCompile](#beforecompile).

## `thisCompilation`

Called while initializing the compilation, can be used to get the current compilation object.

You can use the `compilation` parameter to access the properties of the compilation object, or register [compilation hooks](/api/plugin-api/compilation-hooks.md).

- **Type:** `SyncHook<[Compilation, CompilationParams]>`
- **Arguments:**
  - `compilation`: created [compilation](/api/javascript-api/compilation.md) object
  - `params: CompilationParams`: module factories for this compilation, with `normalModuleFactory` and `contextModuleFactory` properties.


Compilation.ts

- **Example:**

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.thisCompilation.tap('ExamplePlugin', (compilation) => {
      console.log('compilation created:', compilation);

      compilation.hooks.processAssets.tap('ExamplePlugin', (assets) => {
        console.log('Generated assets:', Object.keys(assets));
      });
    });
  }
}
```

## `compilation`

Called after the compilation object is created, can be used to get the current compilation object.

You can use the `compilation` parameter to access the properties of the compilation object, or register [compilation hooks](/api/plugin-api/compilation-hooks.md).

`compilation` hook is called after the [thisCompilation](#thiscompilation) hook, and `thisCompilation` hook is not copied to child compiler, while `compilation` hook is copied to child compiler.

- **Type:** `SyncHook<[Compilation, CompilationParams]>`
- **Arguments:**
  - `compilation`: created [compilation](/api/javascript-api/compilation.md) object
  - `params: CompilationParams`: module factories for this compilation, with `normalModuleFactory` and `contextModuleFactory` properties.


Compilation.ts

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('ExamplePlugin', (compilation) => {
      console.log('compilation created:', compilation);

      compilation.hooks.processAssets.tap('ExamplePlugin', (assets) => {
        console.log('Generated assets:', Object.keys(assets));
      });
    });
  }
}
```

## `make`

Called before the make phase.

In the make phase, Rspack will build the module graph starting from the entry, and use the loader to handle each module.

- **Type:** `AsyncParallelHook<[Compilation]>`
- **Arguments:**
  - `Compilation`: current [compilation](/api/javascript-api/compilation.md) object


Compilation.ts

## `finishMake`

Called after finishing the make phase.

In the make phase, Rspack builds the module graph starting from the entry and uses loaders to handle each module. This hook is called when that process completes.

- **Type:** `AsyncSeriesHook<[Compilation]>`
- **Arguments:**
  - `Compilation`: current [compilation](/api/javascript-api/compilation.md) object


Compilation.ts

## `afterCompile`

Called after the compilation has been finished and sealed, and before Rspack
decides whether to emit the assets ([`shouldEmit`](#shouldemit)).

At this point the assets have been generated and are available on
`compilation.assets`, but nothing has been written to the output directory yet,
so a plugin can still fail the build here without leaving stale files behind.

- **Type:** `AsyncSeriesHook<[Compilation]>`
- **Arguments:**
  - `Compilation`: current [compilation](/api/javascript-api/compilation.md) object


Compilation.ts

## `shouldEmit`

Called before emitting assets. Return `false` to skip emitting assets, or `true` to emit them. Either value stops subsequent taps from running. Return `undefined` or omit the return value to continue to the next tap. If no tap returns a boolean, Rspack emits the assets.

- **Type:** `SyncBailHook<[Compilation], boolean | void>`
- **Arguments:**
  - `Compilation`: current [compilation](/api/javascript-api/compilation.md) object


Compilation.ts

- **Example:**

```js
compiler.hooks.shouldEmit.tap('MyPlugin', (compilation) => {
  // Skip emitting assets if the compilation has errors.
  if (compilation.errors.length > 0) {
    return false;
  }
});
```

## `emit`

Called right before emitting assets to output dir.

- **Type:** `AsyncSeriesHook<[Compilation]>`
- **Arguments:**
  - `Compilation`: current [compilation](/api/javascript-api/compilation.md) object


Compilation.ts

## `afterEmit`

Called after emitting assets to output directory.

- **Type:** `AsyncSeriesHook<[Compilation]>`
- **Arguments:**
  - `Compilation`: current [compilation](/api/javascript-api/compilation.md) object


Compilation.ts

## `done`

Called when the compilation has completed.

- **Type:** `AsyncSeriesHook<Stats>`
- **Arguments:**
  - `Stats`: generated stats object


Stats.ts

## `afterDone`

Called after `done` hook.

- **Type:** `SyncHook<Stats>`
- **Arguments:**
  - `Stats`: generated stats object


Stats.ts

## `failed`

Called if the compilation fails.

- **Type:** `SyncHook<[Error]>`

## `invalid`

Executed when a watching compilation has been invalidated. This hook is not copied to child compilers.

- **Type:** `SyncHook<[string | null, number]>`
- **Arguments:**
  - `fileName`: the file path of the invalid file
  - `changeTime`: the change time of the invalid file

When triggering a re-compilation, this hook can be used to get the changed file path and change time, for example:

```ts
compiler.hooks.invalid.tap('MyPlugin', (fileName, changeTime) => {
  console.log(`Changed file: ${fileName}, change time: ${changeTime}`);
});
```

## `watchClose`

Called when a watching compilation has stopped.

- **Type:** `SyncHook<[]>`

## `shutdown`

Called when the compiler is closing.

- **Type:** `AsyncSeriesHook<[]>`

## infrastructureLog

Called when infrastructure logging is triggered, allowing plugins to intercept, modify, or handle log messages.

This hook provides a way to customize Rspack's infrastructure logs - you can filter specific log types, add custom formatting, or completely override the default logging behavior.

If the hook returns `true`, the default infrastructure logging will be prevented. If it returns `undefined`, the default logging will proceed.

- **Type:** `SyncBailHook<[string, string, any[]], true | void>`
- **Arguments:**
  - `name`: The name of the logger
  - `type`: The log type (e.g., 'log', 'warn', 'error', ...)
  - `args`: An array of arguments passed to the logging method
- **Example:**

```js
class ExamplePlugin {
  apply(compiler) {
    compiler.hooks.infrastructureLog.tap('MyPlugin', (name, type, args) => {
      // Custom logging logic
      if (type === 'error') {
        console.error(`[${name}] ERROR:`, ...args);
        return true; // Prevent default logging
      }

      // Let other log types use default behavior
      return undefined;
    });
  }
}
```

> See [infrastructureLogging](/config/infrastructure-logging.md) to learn more about infrastructure logging.
