webpack-hooks
v1.0.1
Published
Webpack plugin that makes tapping compiler hooks easier
Downloads
3
Maintainers
Readme
What Are Webpack Hooks?
When Webpack runs, it goes through a sequence of build phases. During each phase, it exposes various hooks that developers can tap into to customize behavior.
You can find a full list of compiler hooks here:
https://webpack.js.org/api/compiler-hooks/
Most compiler hooks (before thisCompilation) provide the compiler object. After that, you typically get the compilation object — which exposes its own powerful hook set:
https://webpack.js.org/api/compilation-hooks/
This allows deep control over both the build life-cycle and the actual compilation pipeline. Webpack-hooks plugin allows you to tap both compiler and compilation hooks.
Installation
npm install --save-dev webpack-hooksor
yarn add --dev webpack-hooksUsage
In your Webpack config, import and instantiate the plugin:
const WebpackHooks = require('webpack-hooks');
module.exports = {
output: {
path: '/dist',
publicPath: '/~media/'
},
plugins: [
new WebpackHooks({
beforeRun: (compiler) => { ... },
beforeCompile: (params) => { ... },
compilation: (compilation) => { ... },
// more hooks here...
})
]
};Why WebpackHooks?
Webpack's built-in hook API is mostly geared toward writing full plugins. That comes with boilerplate — class structures, life-cycle setup, and file organization (even for tiny customization).
WebpackHooks removes that friction. Just define the hooks you need, right inside your build config.
Without WebpackHooks
class MyWebpackPlugin {
constructor(options = {}) {
this.options = {
...options
};
}
apply(compiler) {
compiler.hooks.entryOptions.tap(
{ name: 'MyWebpackPlugin' },
(context, entry) => {
console.log(context, entry);
}
);
}
}const MyPlugin = require('./MyPlugin.js');
module.exports = {
plugins: [ new MyPlugin() ]
};With WebpackHooks
const WebpackHooks = require('webpack-hooks');
module.exports = {
plugins: [
new WebpackHooks({
entryOption: (context, entry) => {
console.log(context, entry);
}
})
]
};This is ideal for:
- Small tweaks that don't justify a full plugin
- Rapid prototyping of custom build logic
- Zero plugin organization needed
tap vs. tapPromise
Want to use tapPromise instead of tap? Just mark your function async:
new WebpackHooks({
beforeRun: async (compiler) => {
await doSomething();
}
});Compiler and Compilation hooks
Webpack-hooks plugin indeed supports both Compiler and Compilation hook tapping.
For instance:
new WebpackHooks({
compilation: {
statsFactory: {
result: tapOptions(
{ for: 'compilation' },
(result, context) => {
...
}
),
extract: tapOptions(
{ for: 'compilation' },
(object, compilation) => {
...
}
)
}
}
})In the above example we are tapping Compiler.Compilation Compilation.statusFactor and ultimately statusFactory.results and statusFactory.extract hooks.
tapOptions()
Some hooks (like processAssets) require tap options such as stage or additionalAssets.
You can pass these options via tapOptions():
new WebpackHooks({
compilation: {
processAssets: tapOptions(
{
stage: compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,
additionalAssets: true
},
async (assets) => {
console.log(assets);
}
)
}
});💡 Bonus: Using
asyncwill automatically usetapPromise.
HookMaps and .for('my-preset')
Some hooks (like compilation's statsPreset or statsFactory's deeper hooks) are what is called a HookMap.
This means that in normal plugin syntax, you must chain in a .for('my-preset') into your tapping on hooks that are HookMaps.
In Webpack-hooks plugin, HookMap value is passed in under a tapOptions as a { for: 'my-preset' }:
new WebpackHooks({
compilation: {
statsPreset: tapOptions({ for: 'normal' }, (options) => {
console.log(options);
})
}
})Hook Names
Normally, Webpack requires a name property for each hook tap. With WebpackHooks, it's optional — the fallback is 'WebpackHooks'.
If you want to set a custom name on a hook endpoint:
new WebpackHooks({
entryOption: tapOptions({ name: 'CustomName' }, (context, entry) => {
console.log(context, entry);
})
});if you want to set a custom global value for all hook names:
new MyWebpackPlugin('MyHookName', {
entryOption: (context, entry) => {
console.log(context, entry);
}
})if you don't care, and don't mind they will be named 'WebpackHooks':
new MyWebpackPlugin({
entryOption: (context, entry) => {
console.log(context, entry);
}
})Tests
WebpackHooks comes with a lot of tests.
These helps ensure that hooks can be expressed correctly and function as intended.
Simply run npm run test or yarn test from the root of the plugin to run test.
Running a test will produce a /dist/ directory.
If you would like to change a test, update the root package.json file's test script to use any of the /test/*.*.config.js files.
