webpack构建流程:
1.校验配置文件 2.生成Compiler对象 3.初始化默认插件 4.run/watch:如果运行在watch模式则执行watch方法,否则执行run方法 5.compilation:创建Compilation对象回调compilation相关钩子 6.emit:文件内容准备完成,准备生成文件,这是最后一次修改最终文件的机会 7.afterEmit:文件已经写入磁盘完成 8. done:完成编译
在编写Webpack插件过程中,最常用也是最主要的两个对象就是Webpack提供的Compiler和Compilation,Plugin通过访问Compiler和Compilation对象来完成工作。
- Compiler
对象包含了当前运行Webpack的配置,包括entry、output、loaders等配置,这个对象在启动Webpack时被实例化,而且是全局唯一的。Plugin可以通过该对象获取到Webpack的配置信息进行处理。 Compilation 对象可以理解编译对象,包含了模块、依赖、文件等信息。在开发模式下运行Webpack时,每修改一次文件都会产生一个新的Compilation对象,Plugin可以访问到本次编译过程中的模块、依赖、文件内容等信息。
常用钩子函数: Tapable是Webpack的一个核心工具,Webpack中许多对象扩展自Tapable类。Tapable类暴露了tap、tapAsync和tapPromise方法,可以根据钩子的同步/异步方式来选择一个函数注入逻辑。
- tap 同步钩子
- tapAsync 异步钩子,通过callback回调告诉Webpack异步执行完毕
- tapPromise 异步钩子,返回一个Promise告诉Webpack异步执行完毕
插件使用:
plugins: [
new CopyRightPlugin(),
]
因此插件是一个可实例化的对象(包含apply方法的对象)
class MyPlugin{
apply(compiler){
console.log("MyPlugin 启动~")
compiler.hooks.emit.tap('MyWebpackPlugin', (compilation) => {});
}
}
module.exports = MyWebpackPlugin;
举例: 生成清单文件插件
class MyWebpackPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('MyWebpackPlugin', (compilation, callback) => {
const manifest = {};
for (const name of Object.keys(compilation.assets)) {
manifest[name] = compilation.assets[name].size();
}
compilation.assets['manifest.json'] = {
source() {
return JSON.stringify(manifest);
},
size() {
return this.source().length;
}
};
callback();
});
}
}
module.exports = MyWebpackPlugin;
|