插件可以访问 webpack 打包生命周期中涉及的资源,做一些额外的操作。
在 webpack 配置文件中有个 plugins 的选项,接收用户自定义的插件。
// webpack.config.js
module.exports = {
plugins: [
new MyCustomPlugin()
],
}
1 定义
插件通常定义如下所示,取一个有 apply 方法的类
class MyExampleWebpackPlugin {
constructor(options) {
this.options = options;
}
// Define `apply` as its prototype method which is supplied with
// compiler as its argument
apply(compiler) {
// Specify the event hook to attach to
compiler.hooks.emit.tapAsync(
'MyExampleWebpackPlugin',
(compilation, callback) => {
callback();
}
);
}
}
2 hook
webpack 内部使用 tapable 分发事件。一般通过如下形式注册
compiler.hooks.someHook.tap('MyPlugin', (params) => {
/* ... */
});
其中 someHook 是某个生命周期的 hook,如:
- emit (AsyncSeriesHook) : 在打包输出前触发
- afterEmit (AsyncSeriesHook) : 在打包输出后触发
全部参考:https://webpack.js.org/api/compiler-hooks/
2.1 文件读取
负责文件生成的 hook 叫 emit,它是一个 AsyncSeriesHook 。
emit 生成文件阶段,读取的是 compilation.assets 对象的值
module.exports = class ZipPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.emit.tapAsync('ZipPlugin', (compilation, cb) => {
for (let filename in compilation.assets) {
const source = compilation.assets[filename].source();
// do something
}
// call cb()
});
}
}
2.2 文件写入
使用 webpack-sources 包进行写入
const RawSource = require('webpack-sources').RawSource;
compilation.assets[outputPath] = new RawSource(content);