3-12 webpack 里面的插件是如何实现的?
webpack 插件 是一个 函数,这个函数的原型上必须携带一个 apply 的方法,供给 webpack 使用,webpack 会调用 apply 并传入一个 compiler
关注核心:Compiler和Compilation
在开发Plugin时最常用的两个对象是Compiler和Compilation,他们是Plugin和webpack之间的桥梁,Compiler和Compilation的含义如下:
-
Compiler对象包含了Webpack所有的配置信息,包含options,loaders,plugins等信息,这个对象在Webpack启动的时候被初始化,在webpack4当中是唯一的实例,可以简单的认为他是webpack的实例(webpack5当中的已经改版了,已经允许多个webpack实例的存在)
-
Compilation对象包含了当前的模块资源,编译生成资源,变化的文件,当webpack以开发模式运行时,每当检测到一个文件变化一次新的Compilation将被创建,Compilation对象也提供了很多事件回调提供插件做拓展,通过Compilation也能读取到整个Compiler对象。
Compiler和Compilation的区别在于Compiler代表了整个Webpack从启动到关闭的声明周期,而Compilation只代表了一次新的编译。 或者换个更通俗的说法: Compiler说明了什么时间要做事,但是compilation说明了要做什么事情
事件流
webpack通过Tapable来组织这条生产线。 webpack的事件流机制用了观察者模式。 Compiler和Compilation都继承自Tabable可以直接在Compiler和Compilation对象上关闭和监听事件。
class Plugin {
apply(compiler) {
compiler.hooks.afterEmit.tap('testEmitAndAfterEmit', (compilation)=> {
console.log('112')
})
compiler.hooks.emit.tap('testEmitAndAfterEmit', (compilation)=> {
console.log('111')
})
compiler.hooks.emit.tapAsync('testEmitAndAfterEmit', (compilation,cb)=> {
setTimeout(()=> {
console.log('222')
cb()
},1000)
})
}
}
module.exports = Plugin