参考资料
webpack自定义hook 通过监听compiler实例提供的hook来达到修改文件的效果。
plugin
介绍
当我们想要在webpack构建文件的流程中做出一些自定义操作,比如查看构建时间、代码压缩、增删改查文件的时候,就可以考虑自定义plugin。
plugin工作模式
Compiler与插件的协作模式并不是Compiler直接调用这些插件,而是由Compiler暴露出工作流程中的Hook(钩子),让插件监听这些Hook,并在适当的时机完成相应的工作。
举例:
// MySyncWebpackPlugin.js
class MySyncWebpackPlugin {
apply(compiler) {
compiler.hooks.afterResolvers.tap('MySyncWebpackPlugin', (compiler) => {
console.log('[ compiler ] >', compiler);
});
}
}
// webpack.config.js
const MySyncWebpackPlugin = require('./MySyncWebpackPlugin.js')
module.exports = {
...
plugins:[
new MySyncWebpackPlugin()
]
...
}
各种hooks与tap类型简单介绍:
监听了hooks,但是使用的方法是tapAsync。具体使用哪个方法来监听,取决于该Hook在Webpack内部是如何定义的。可通过如下表格查看对应的tap方法。
使用tap方法时,回调函数仅可以包含由hook提供的参数,且只允许执行同步逻辑。
tapAsync方法允许执行异步逻辑,最后通过参数中的callback函数结束插件的执行
class MyAsyncWebpackPlugin {
apply(compiler) {
compiler.hooks.done.tapAsync(
'MyAsyncWebpackPlugin',
(stats, cb) => {
setTimeout(() => {
console.log('[ stats ] >', stats);
cb();
}, 1000);
});
}
}
}
tapPromise基本上只是tapAsync的另一种写法
class MyAsyncWebpackPlugin {
apply(compiler) {
compiler.hooks.done.tapPromise(
'MyAsyncWebpackPlugin',
(stats) => {
return new Promise((resolve) => setTimeout(resolve, 1000))
.then(() => {
console.log('[ stats ] >', stats);
});
}
);
}
}
对于绝大多数的Hook来说,同一时刻只允许有一个插件在工作
,在上一个插件被触发而未执行完其逻辑之前,下一个插件不会被触发.对于监听了同一个Hook的不同插件来说,引入的顺序就是执行的顺序。
Sync、Async表示其是否可以执行异步逻辑,Parallel表示多个插件可以并行执行任务。
Bail关键字表示当一个Hook有多个插件监听时,一旦有一个插件返回了非undefined的值,则该Hook提前终止,即便后面有其他插件也不会继续执行了
Waterfall关键字代表前一个插件的结果将作为后一个插件的输入。
关键字Series总是与Async出现在一起,意思是逐个地执行异步任务。