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

# Plugin System Overview

> Learn how to create webpack plugins using the Tapable hook system

## What is a Plugin?

Plugins are the backbone of webpack. Webpack itself is built on the same plugin system that you use in your webpack configuration. They allow you to hook into the entire compilation lifecycle and customize webpack's behavior.

## Basic Plugin Structure

A webpack plugin is a JavaScript object that has an `apply` method. This `apply` method is called by the webpack compiler, giving the plugin access to the entire compilation lifecycle.

```javascript theme={null}
class MyPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      // Access compilation hooks
      compilation.hooks.optimize.tap('MyPlugin', () => {
        console.log('Optimizing...');
      });
    });
  }
}

module.exports = MyPlugin;
```

## Plugin Anatomy

### 1. The `apply` Method

Every plugin must have an `apply` method that receives the compiler instance:

```javascript theme={null}
apply(compiler) {
  // Plugin logic here
}
```

### 2. Tapping into Hooks

Webpack uses [Tapable](./tapable) to expose hooks. You can tap into these hooks using:

* `tap` - Synchronous hook
* `tapAsync` - Asynchronous hook with callback
* `tapPromise` - Asynchronous hook with promises

```javascript theme={null}
// Synchronous
compiler.hooks.run.tap('MyPlugin', (compiler) => {
  console.log('Webpack is running');
});

// Asynchronous with callback
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
  setTimeout(() => {
    console.log('Done with async work');
    callback();
  }, 1000);
});

// Asynchronous with Promise
compiler.hooks.afterEmit.tapPromise('MyPlugin', (compilation) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Done with async work');
      resolve();
    }, 1000);
  });
});
```

## Real-World Example: BannerPlugin

Here's a simplified version of webpack's BannerPlugin:

```javascript theme={null}
const { ConcatSource } = require('webpack-sources');

class BannerPlugin {
  constructor(options) {
    this.banner = options.banner;
  }

  apply(compiler) {
    compiler.hooks.compilation.tap('BannerPlugin', (compilation) => {
      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(this.banner, '\n', old);
              });
            }
          }
        }
      );
    });
  }
}
```

## Plugin Types

### Compiler Plugins

Hook into the compiler lifecycle for tasks that happen once per build:

```javascript theme={null}
compiler.hooks.beforeRun.tap('MyPlugin', (compiler) => {
  // Runs before webpack starts
});
```

### Compilation Plugins

Hook into each compilation for tasks that happen during module processing:

```javascript theme={null}
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
  compilation.hooks.buildModule.tap('MyPlugin', (module) => {
    // Runs before each module is built
  });
});
```

### Module Factory Plugins

Customize how modules are created and resolved:

```javascript theme={null}
compiler.hooks.compilation.tap(
  'MyPlugin',
  (compilation, { normalModuleFactory }) => {
    normalModuleFactory.hooks.parser
      .for('javascript/auto')
      .tap('MyPlugin', (parser) => {
        // Customize the JavaScript parser
      });
  }
);
```

## Key Concepts

### Compiler vs Compilation

* **Compiler**: Represents the entire webpack configuration. Created once per webpack process.
* **Compilation**: Represents a single build. In watch mode, a new compilation is created on each file change.

### Hook Stages

Many hooks support a `stage` option to control execution order:

```javascript theme={null}
compilation.hooks.processAssets.tap(
  {
    name: 'MyPlugin',
    stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE
  },
  (assets) => {
    // Process assets during optimization stage
  }
);
```

Common stages:

* `PROCESS_ASSETS_STAGE_ADDITIONAL` - Add additional assets
* `PROCESS_ASSETS_STAGE_PRE_PROCESS` - Basic preprocessing
* `PROCESS_ASSETS_STAGE_OPTIMIZE` - Optimize assets
* `PROCESS_ASSETS_STAGE_SUMMARIZE` - Summarize assets

## Next Steps

* [Compiler Hooks](./compiler-hooks) - Learn about compiler lifecycle hooks
* [Compilation Hooks](./compilation-hooks) - Explore compilation hooks
* [Module Factories](./module-factories) - Understand module creation
* [Parser Hooks](./parser) - Customize code parsing
* [Tapable](./tapable) - Master the hook system

## Best Practices

1. **Name your taps**: Always provide a clear plugin name when tapping hooks
2. **Handle errors**: Properly handle errors in async hooks
3. **Clean up**: Remove side effects in watch mode
4. **Document**: Add comments explaining what your plugin does
5. **Test**: Write tests for different webpack configurations
