Documentation Index
Fetch the complete documentation index at: https://docs.webpack.js.org/llms.txt
Use this file to discover all available pages before exploring further.
The Compiler module is the main engine that creates a compilation instance with all the options passed through the webpack configuration. It extends Tapable and provides lifecycle hooks.
Accessing Compiler Hooks
Compiler hooks are accessed in your plugin’s apply method:
class MyPlugin {
apply(compiler) {
compiler.hooks.run.tap('MyPlugin', (compiler) => {
console.log('The webpack build process is starting');
});
}
}
Hook Types Reference
Each hook is an instance of a Tapable hook class. The type determines how you can tap into it:
SyncHook - Use .tap() only
SyncBailHook - Use .tap(), can return value to exit early
AsyncSeriesHook - Use .tap(), .tapAsync(), or .tapPromise()
AsyncParallelHook - Use .tap(), .tapAsync(), or .tapPromise() (runs in parallel)
Lifecycle Hooks
initialize
Called when the compiler is initialized.
compiler.hooks.initialize.tap('MyPlugin', () => {
console.log('Compiler initialized');
});
environment
Called after the environment is set up.
compiler.hooks.environment.tap('MyPlugin', () => {
// Prepare environment
});
afterEnvironment
Called after environment setup is complete.
compiler.hooks.afterEnvironment.tap('MyPlugin', () => {
// Environment is ready
});
afterPlugins
Called after all plugins from the configuration have been applied.
compiler.hooks.afterPlugins.tap('MyPlugin', (compiler) => {
console.log('All plugins applied');
});
afterResolvers
Called after the resolvers are set up.
compiler.hooks.afterResolvers.tap('MyPlugin', (compiler) => {
// Modify resolvers if needed
});
entryOption
SyncBailHook<[string, Entry]>
Called after the entry configuration has been processed. Return true to prevent default entry processing.
compiler.hooks.entryOption.tap('MyPlugin', (context, entry) => {
// Custom entry handling
});
Build Lifecycle Hooks
beforeRun
AsyncSeriesHook<[Compiler]>
Called before the compiler starts running. Perfect for cleanup or setup tasks.
compiler.hooks.beforeRun.tapAsync('MyPlugin', (compiler, callback) => {
// Prepare for build
callback();
});
Example from source (lib/Compiler.js:607):
this.hooks.beforeRun.callAsync(this, (err) => {
if (err) return finalCallback(err);
this.hooks.run.callAsync(this, (err) => {
// Continue build process
});
});
run
AsyncSeriesHook<[Compiler]>
Called when the compiler starts running.
compiler.hooks.run.tapPromise('MyPlugin', async (compiler) => {
console.log('Build started');
});
watchRun
AsyncSeriesHook<[Compiler]>
Called when watch mode is triggered. Receives the compiler instance.
compiler.hooks.watchRun.tapAsync('MyPlugin', (compiler, callback) => {
console.log('Watch compilation started');
// Access changed files
const changedFiles = compiler.modifiedFiles;
callback();
});
Compilation Hooks
beforeCompile
AsyncSeriesHook<[CompilationParams]>
Called before compilation parameters are created.
compiler.hooks.beforeCompile.tapAsync(
'MyPlugin',
(params, callback) => {
// params.normalModuleFactory
// params.contextModuleFactory
callback();
}
);
compile
SyncHook<[CompilationParams]>
Called immediately before a new compilation is created.
compiler.hooks.compile.tap('MyPlugin', (params) => {
console.log('Creating new compilation');
});
thisCompilation
SyncHook<[Compilation, CompilationParams]>
Called when a compilation is created, before compilation hook.
compiler.hooks.thisCompilation.tap(
'MyPlugin',
(compilation, params) => {
// Called before compilation hook
}
);
compilation
SyncHook<[Compilation, CompilationParams]>
Called when a compilation is created. This is your main entry point for compilation-level hooks.
compiler.hooks.compilation.tap(
'MyPlugin',
(compilation, { normalModuleFactory }) => {
// Access compilation hooks
compilation.hooks.buildModule.tap('MyPlugin', (module) => {
// Module is being built
});
}
);
Example: DefinePlugin (lib/DefinePlugin.js:388):
compiler.hooks.compilation.tap(
'DefinePlugin',
(compilation, { normalModuleFactory }) => {
const handler = (parser) => {
// Walk definitions and hook into parser
};
normalModuleFactory.hooks.parser
.for('javascript/auto')
.tap('DefinePlugin', handler);
}
);
make
AsyncParallelHook<[Compilation]>
Called when compilation starts. This is where entries are processed.
compiler.hooks.make.tapAsync('MyPlugin', (compilation, callback) => {
// Add entries or process modules
callback();
});
finishMake
AsyncSeriesHook<[Compilation]>
Called when make phase finishes.
compiler.hooks.finishMake.tapAsync('MyPlugin', (compilation, callback) => {
// Make phase complete
callback();
});
afterCompile
AsyncSeriesHook<[Compilation]>
Called after compilation finishes.
compiler.hooks.afterCompile.tapAsync('MyPlugin', (compilation, callback) => {
// Compilation complete, before sealing
callback();
});
Module Factory Hooks
normalModuleFactory
SyncHook<[NormalModuleFactory]>
Called after creating a NormalModuleFactory.
compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser) => {
// Customize parser
});
});
contextModuleFactory
SyncHook<[ContextModuleFactory]>
Called after creating a ContextModuleFactory.
compiler.hooks.contextModuleFactory.tap('MyPlugin', (factory) => {
// Customize context module creation
});
Emit Hooks
shouldEmit
SyncBailHook<[Compilation], boolean | void>
Return false to prevent emitting assets.
compiler.hooks.shouldEmit.tap('MyPlugin', (compilation) => {
// Return false to skip emit
if (compilation.errors.length > 0) {
return false;
}
});
emit
AsyncSeriesHook<[Compilation]>
Called immediately before assets are emitted to output directory.
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
// Modify assets before writing to disk
for (const filename in compilation.assets) {
console.log(`Emitting ${filename}`);
}
callback();
});
assetEmitted
AsyncSeriesHook<[string, AssetEmittedInfo]>
Called when an asset has been written to disk.
compiler.hooks.assetEmitted.tap(
'MyPlugin',
(file, { content, outputPath, targetPath }) => {
console.log(`Asset emitted: ${file}`);
}
);
afterEmit
AsyncSeriesHook<[Compilation]>
Called after assets have been emitted.
compiler.hooks.afterEmit.tapAsync('MyPlugin', (compilation, callback) => {
// All assets written to disk
callback();
});
Completion Hooks
done
Called when compilation completes successfully.
compiler.hooks.done.tap('MyPlugin', (stats) => {
console.log('Build completed');
console.log(stats.toString());
});
afterDone
Called after done hook completes.
compiler.hooks.afterDone.tap('MyPlugin', (stats) => {
// Final cleanup
});
failed
Called when compilation fails.
compiler.hooks.failed.tap('MyPlugin', (error) => {
console.error('Build failed:', error);
});
Watch Mode Hooks
invalid
SyncHook<[string | null, number]>
Called when a watched file changes.
compiler.hooks.invalid.tap('MyPlugin', (filename, changeTime) => {
console.log(`File changed: ${filename}`);
});
watchClose
Called when watch mode stops.
compiler.hooks.watchClose.tap('MyPlugin', () => {
console.log('Watch mode stopped');
});
Other Hooks
shutdown
Called when compiler is shutting down.
compiler.hooks.shutdown.tapAsync('MyPlugin', (callback) => {
// Cleanup resources
callback();
});
infrastructureLog
SyncBailHook<[string, string, any[]], true | void>
Custom infrastructure logging.
compiler.hooks.infrastructureLog.tap(
'MyPlugin',
(origin, type, args) => {
// Custom logging
}
);
Complete Example
class MyCompilerPlugin {
apply(compiler) {
// Setup phase
compiler.hooks.environment.tap('MyPlugin', () => {
console.log('Environment setup');
});
// Before build
compiler.hooks.beforeRun.tapAsync('MyPlugin', (compiler, callback) => {
console.log('Preparing to build');
callback();
});
// During compilation
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
compilation.hooks.buildModule.tap('MyPlugin', (module) => {
console.log('Building module:', module.identifier());
});
});
// After emit
compiler.hooks.afterEmit.tapAsync('MyPlugin', (compilation, callback) => {
console.log('Assets emitted');
callback();
});
// Build complete
compiler.hooks.done.tap('MyPlugin', (stats) => {
console.log('Build completed in', stats.endTime - stats.startTime, 'ms');
});
}
}
See Also