> ## 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.

# Compilation Hooks

> Reference for webpack Compilation lifecycle hooks

The `Compilation` module is created by the `Compiler` and represents a single build of the assets. In watch mode, a new compilation is created each time a file changes.

## Accessing Compilation Hooks

Access compilation hooks through the compiler's `compilation` hook:

```javascript theme={null}
class MyPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      compilation.hooks.buildModule.tap('MyPlugin', (module) => {
        console.log('Building module');
      });
    });
  }
}
```

## Module Hooks

### `buildModule`

```typescript theme={null}
SyncHook<[Module]>
```

Called before a module is built.

```javascript theme={null}
compilation.hooks.buildModule.tap('MyPlugin', (module) => {
  console.log('Building:', module.identifier());
});
```

### `rebuildModule`

```typescript theme={null}
SyncHook<[Module]>
```

Called when a module is rebuilt in watch mode.

```javascript theme={null}
compilation.hooks.rebuildModule.tap('MyPlugin', (module) => {
  console.log('Rebuilding:', module.identifier());
});
```

### `succeedModule`

```typescript theme={null}
SyncHook<[Module]>
```

Called when a module is successfully built.

```javascript theme={null}
compilation.hooks.succeedModule.tap('MyPlugin', (module) => {
  console.log('Successfully built:', module.identifier());
});
```

### `failedModule`

```typescript theme={null}
SyncHook<[Module, WebpackError]>
```

Called when a module build fails.

```javascript theme={null}
compilation.hooks.failedModule.tap('MyPlugin', (module, error) => {
  console.error('Failed to build:', module.identifier(), error);
});
```

### `stillValidModule`

```typescript theme={null}
SyncHook<[Module]>
```

Called when a module is still valid (cached).

```javascript theme={null}
compilation.hooks.stillValidModule.tap('MyPlugin', (module) => {
  console.log('Module still valid:', module.identifier());
});
```

### `finishModules`

```typescript theme={null}
AsyncSeriesHook<[Iterable<Module>]>
```

Called when all modules have been built.

```javascript theme={null}
compilation.hooks.finishModules.tapAsync(
  'MyPlugin',
  (modules, callback) => {
    console.log(`Finished building ${modules.size} modules`);
    callback();
  }
);
```

### `finishRebuildingModule`

```typescript theme={null}
AsyncSeriesHook<[Module]>
```

Called when a module finishes rebuilding.

```javascript theme={null}
compilation.hooks.finishRebuildingModule.tapAsync(
  'MyPlugin',
  (module, callback) => {
    console.log('Finished rebuilding:', module.identifier());
    callback();
  }
);
```

## Entry Hooks

### `addEntry`

```typescript theme={null}
SyncHook<[Dependency, EntryOptions]>
```

Called when an entry is added.

```javascript theme={null}
compilation.hooks.addEntry.tap('MyPlugin', (entry, options) => {
  console.log('Adding entry:', options.name);
});
```

### `succeedEntry`

```typescript theme={null}
SyncHook<[Dependency, EntryOptions, Module]>
```

Called when an entry is successfully processed.

```javascript theme={null}
compilation.hooks.succeedEntry.tap(
  'MyPlugin',
  (entry, options, module) => {
    console.log('Entry succeeded:', options.name);
  }
);
```

### `failedEntry`

```typescript theme={null}
SyncHook<[Dependency, EntryOptions, Error]>
```

Called when an entry fails.

```javascript theme={null}
compilation.hooks.failedEntry.tap(
  'MyPlugin',
  (entry, options, error) => {
    console.error('Entry failed:', options.name, error);
  }
);
```

## Sealing Hooks

### `seal`

```typescript theme={null}
SyncHook<[]>
```

Called when compilation sealing begins. After this, no more modules are added.

```javascript theme={null}
compilation.hooks.seal.tap('MyPlugin', () => {
  console.log('Compilation sealed');
});
```

### `unseal`

```typescript theme={null}
SyncHook<[]>
```

Called when compilation is unsealed.

```javascript theme={null}
compilation.hooks.unseal.tap('MyPlugin', () => {
  console.log('Compilation unsealed');
});
```

### `afterSeal`

```typescript theme={null}
AsyncSeriesHook<[]>
```

Called after compilation is sealed.

```javascript theme={null}
compilation.hooks.afterSeal.tapAsync('MyPlugin', (callback) => {
  console.log('After seal');
  callback();
});
```

## Chunk Hooks

### `beforeChunks`

```typescript theme={null}
SyncHook<[]>
```

Called before chunk creation.

```javascript theme={null}
compilation.hooks.beforeChunks.tap('MyPlugin', () => {
  console.log('Before chunks created');
});
```

### `afterChunks`

```typescript theme={null}
SyncHook<[Iterable<Chunk>]>
```

Called after chunks are created. Perfect for analyzing the chunk graph.

```javascript theme={null}
compilation.hooks.afterChunks.tap('MyPlugin', (chunks) => {
  console.log(`Created ${chunks.size} chunks`);
  for (const chunk of chunks) {
    console.log('Chunk:', chunk.id, 'files:', Array.from(chunk.files));
  }
});
```

## Optimization Hooks

### `optimize`

```typescript theme={null}
SyncHook<[]>
```

Called at the beginning of optimization phase.

```javascript theme={null}
compilation.hooks.optimize.tap('MyPlugin', () => {
  console.log('Optimization started');
});
```

### `optimizeModules`

```typescript theme={null}
SyncBailHook<[Iterable<Module>]>
```

Called during module optimization. Return `true` to skip remaining optimizations.

```javascript theme={null}
compilation.hooks.optimizeModules.tap('MyPlugin', (modules) => {
  for (const module of modules) {
    // Optimize module
  }
});
```

### `afterOptimizeModules`

```typescript theme={null}
SyncHook<[Iterable<Module>]>
```

Called after module optimization.

```javascript theme={null}
compilation.hooks.afterOptimizeModules.tap('MyPlugin', (modules) => {
  console.log('Module optimization complete');
});
```

### `optimizeChunks`

```typescript theme={null}
SyncBailHook<[Iterable<Chunk>, ChunkGroup[]]>
```

Called during chunk optimization.

```javascript theme={null}
compilation.hooks.optimizeChunks.tap(
  'MyPlugin',
  (chunks, chunkGroups) => {
    for (const chunk of chunks) {
      // Optimize chunk
    }
  }
);
```

### `afterOptimizeChunks`

```typescript theme={null}
SyncHook<[Iterable<Chunk>, ChunkGroup[]]>
```

Called after chunk optimization.

```javascript theme={null}
compilation.hooks.afterOptimizeChunks.tap(
  'MyPlugin',
  (chunks, chunkGroups) => {
    console.log('Chunk optimization complete');
  }
);
```

### `optimizeTree`

```typescript theme={null}
AsyncSeriesHook<[Iterable<Chunk>, Iterable<Module>]>
```

Optimize the dependency tree.

```javascript theme={null}
compilation.hooks.optimizeTree.tapAsync(
  'MyPlugin',
  (chunks, modules, callback) => {
    // Optimize module and chunk tree
    callback();
  }
);
```

### `optimizeChunkModules`

```typescript theme={null}
AsyncSeriesBailHook<[Iterable<Chunk>, Iterable<Module>]>
```

Optimize modules within chunks.

```javascript theme={null}
compilation.hooks.optimizeChunkModules.tapAsync(
  'MyPlugin',
  (chunks, modules, callback) => {
    // Optimize how modules are assigned to chunks
    callback();
  }
);
```

## Module & Chunk IDs

### `moduleIds`

```typescript theme={null}
SyncHook<[Iterable<Module>]>
```

Called to assign module IDs.

```javascript theme={null}
compilation.hooks.moduleIds.tap('MyPlugin', (modules) => {
  for (const module of modules) {
    if (module.id === null) {
      // Assign custom ID
      module.id = customIdGenerator();
    }
  }
});
```

### `chunkIds`

```typescript theme={null}
SyncHook<[Iterable<Chunk>]>
```

Called to assign chunk IDs.

```javascript theme={null}
compilation.hooks.chunkIds.tap('MyPlugin', (chunks) => {
  for (const chunk of chunks) {
    if (chunk.id === null) {
      // Assign custom ID
      chunk.id = customIdGenerator();
    }
  }
});
```

## Hash Hooks

### `beforeHash`

```typescript theme={null}
SyncHook<[]>
```

Called before hashing.

```javascript theme={null}
compilation.hooks.beforeHash.tap('MyPlugin', () => {
  console.log('Before hash generation');
});
```

### `afterHash`

```typescript theme={null}
SyncHook<[]>
```

Called after compilation is hashed.

```javascript theme={null}
compilation.hooks.afterHash.tap('MyPlugin', () => {
  console.log('Hash:', compilation.hash);
});
```

### `fullHash`

```typescript theme={null}
SyncHook<[Hash]>
```

Called to add custom data to the full hash.

```javascript theme={null}
compilation.hooks.fullHash.tap('MyPlugin', (hash) => {
  hash.update('my custom data');
});
```

### `chunkHash`

```typescript theme={null}
SyncHook<[Chunk, Hash, ChunkHashContext]>
```

Called to add custom data to each chunk's hash.

```javascript theme={null}
compilation.hooks.chunkHash.tap('MyPlugin', (chunk, hash, context) => {
  hash.update('my custom chunk data');
});
```

### `contentHash`

```typescript theme={null}
SyncHook<[Chunk]>
```

Called to create content hash for a chunk.

```javascript theme={null}
compilation.hooks.contentHash.tap('MyPlugin', (chunk) => {
  // Update content hash
});
```

## Asset Hooks

### `beforeModuleAssets`

```typescript theme={null}
SyncHook<[]>
```

Called before module assets are created.

```javascript theme={null}
compilation.hooks.beforeModuleAssets.tap('MyPlugin', () => {
  console.log('Creating module assets');
});
```

### `beforeChunkAssets`

```typescript theme={null}
SyncHook<[]>
```

Called before chunk assets are created.

```javascript theme={null}
compilation.hooks.beforeChunkAssets.tap('MyPlugin', () => {
  console.log('Creating chunk assets');
});
```

### `processAssets`

```typescript theme={null}
AsyncSeriesHook<[CompilationAssets]>
```

The main hook for processing assets. Supports stages for ordering.

```javascript theme={null}
const { Compilation } = require('webpack');

compilation.hooks.processAssets.tap(
  {
    name: 'MyPlugin',
    stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE
  },
  (assets) => {
    for (const name in assets) {
      console.log('Processing asset:', name);
      // Modify or analyze asset
    }
  }
);
```

**Asset Processing Stages:**

```javascript theme={null}
// Add additional assets to compilation
PROCESS_ASSETS_STAGE_ADDITIONAL = -2000

// Basic preprocessing
PROCESS_ASSETS_STAGE_PRE_PROCESS = -1000

// Derive new assets from existing
PROCESS_ASSETS_STAGE_DERIVED = -200

// Add additional sections to existing assets
PROCESS_ASSETS_STAGE_ADDITIONS = -100

// Optimize existing assets
PROCESS_ASSETS_STAGE_OPTIMIZE = 100

// Optimize size of assets
PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE = 400

// Add development tooling
PROCESS_ASSETS_STAGE_DEV_TOOLING = 500

// Optimize asset transfer
PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER = 700

// Analyze existing assets
PROCESS_ASSETS_STAGE_ANALYSE = 4000

// Summarize the list of assets
PROCESS_ASSETS_STAGE_SUMMARIZE = Infinity
```

**Example: BannerPlugin** (lib/BannerPlugin.js:100):

```javascript theme={null}
compilation.hooks.processAssets.tap(
  { 
    name: 'BannerPlugin', 
    stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS 
  },
  () => {
    for (const chunk of compilation.chunks) {
      for (const file of chunk.files) {
        compilation.updateAsset(file, (old) => {
          return new ConcatSource(banner, '\n', old);
        });
      }
    }
  }
);
```

### `afterProcessAssets`

```typescript theme={null}
SyncHook<[CompilationAssets]>
```

Called after asset processing is complete.

```javascript theme={null}
compilation.hooks.afterProcessAssets.tap('MyPlugin', (assets) => {
  console.log('Asset processing complete');
});
```

### `moduleAsset`

```typescript theme={null}
SyncHook<[Module, string]>
```

Called when a module asset is created.

```javascript theme={null}
compilation.hooks.moduleAsset.tap('MyPlugin', (module, filename) => {
  console.log('Module asset:', filename);
});
```

### `chunkAsset`

```typescript theme={null}
SyncHook<[Chunk, string]>
```

Called when a chunk asset is created.

```javascript theme={null}
compilation.hooks.chunkAsset.tap('MyPlugin', (chunk, filename) => {
  console.log('Chunk asset:', filename);
});
```

## Record Hooks

### `record`

```typescript theme={null}
SyncHook<[Compilation, Records]>
```

Store information about the compilation.

```javascript theme={null}
compilation.hooks.record.tap('MyPlugin', (compilation, records) => {
  records.myPluginData = { /* custom data */ };
});
```

## Stats Hooks

### `statsPreset`

```typescript theme={null}
HookMap<SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>>
```

Customize stats presets.

```javascript theme={null}
compilation.hooks.statsPreset
  .for('my-preset')
  .tap('MyPlugin', (options, context) => {
    options.assets = true;
    options.modules = true;
  });
```

### `statsNormalize`

```typescript theme={null}
SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>
```

Normalize stats options.

```javascript theme={null}
compilation.hooks.statsNormalize.tap('MyPlugin', (options, context) => {
  // Normalize options
});
```

### `statsFactory`

```typescript theme={null}
SyncHook<[StatsFactory, NormalizedStatsOptions]>
```

Customize how stats are created.

```javascript theme={null}
compilation.hooks.statsFactory.tap('MyPlugin', (statsFactory, options) => {
  statsFactory.hooks.extract.tap('MyPlugin', (object, data) => {
    // Extract custom stats
  });
});
```

### `statsPrinter`

```typescript theme={null}
SyncHook<[StatsPrinter, NormalizedStatsOptions]>
```

Customize how stats are printed.

```javascript theme={null}
compilation.hooks.statsPrinter.tap('MyPlugin', (statsPrinter, options) => {
  statsPrinter.hooks.print.tap('MyPlugin', (value, context) => {
    // Custom printing
  });
});
```

## Runtime Requirements Hooks

### `additionalTreeRuntimeRequirements`

```typescript theme={null}
SyncHook<[Chunk, RuntimeRequirements, RuntimeRequirementsContext]>
```

Add runtime requirements for a chunk.

```javascript theme={null}
compilation.hooks.additionalTreeRuntimeRequirements.tap(
  'MyPlugin',
  (chunk, runtimeRequirements, context) => {
    runtimeRequirements.add('myCustomRuntime');
  }
);
```

## Complete Example

```javascript theme={null}
class MyCompilationPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      // Module building
      compilation.hooks.buildModule.tap('MyPlugin', (module) => {
        console.log('Building:', module.identifier());
      });

      // Optimize modules
      compilation.hooks.optimizeModules.tap('MyPlugin', (modules) => {
        console.log(`Optimizing ${modules.size} modules`);
      });

      // Process assets
      compilation.hooks.processAssets.tap(
        {
          name: 'MyPlugin',
          stage: compilation.PROCESS_ASSETS_STAGE_OPTIMIZE
        },
        (assets) => {
          for (const name in assets) {
            const asset = assets[name];
            console.log(`Asset: ${name}, Size: ${asset.size()}`);
          }
        }
      );

      // After seal
      compilation.hooks.afterSeal.tapAsync('MyPlugin', (callback) => {
        console.log('Compilation sealed');
        callback();
      });
    });
  }
}
```

## See Also

* [Compiler Hooks](./compiler-hooks) - Hooks for the compiler lifecycle
* [Module Factories](./module-factories) - Module creation hooks
* [Parser Hooks](./parser) - Code parsing hooks
