webpack_注册hooks

76 阅读3分钟

接前文plugin浅析记录我简单自定义了一个plugin代码如下:

class TestP {
    constructor() {
        console.log('test  TestPlugin')
    }
    apply(complier) {
        console.log('test  TestPluginApply')
    }
}
module.exports = TestP

Tapable提供的插件统一接口的类型有 AsyncParallelHook(异步并行钩子),AsyncSeriesHook(异步串行钩子),SyncHook(同步),SyncBailHook(同步熔断 即返回内容return一个非undefined的值,则不再继续执行后面的监听函数)....10种

注册钩子的方法
  • 1.找到需要使用的钩子函数,从官方文档了解钩子的类型
  • 2.根据钩子类型,参数类型 挂载方法在插件apply方法中找到对应的周期函数添加自定义事件
complier hooks注册

栗子

egs:使用complier的周期函数 `environment` 为异步钩子

class TestP {
    constructor() {
        console.log('test  TestPlugin')
    }
    apply(complier) {
        console.log('test  TestPluginApply')
          // 注册到环境准备好执行的周期中   environment为异步钩子
        complier.hooks.environment.tap('TestP', () => {
            console.log('test plugin environment ')
        })
    }
}
module.exports = TestP

控制台:

image.png

根据钩子的接入类型不一致注册事件的时候写法也有多种异步钩子可以接受多个方法

emit

emitAsyncSeriesHook异步串行钩子

emit.jpg

它挂载的方法是依次执行(同步)的, 可以用tap,tapAsync,tapPromise都能注册只是后续参数不一致按需使用

返回执行内容写上延时
      complier.hooks.emit.tap('TestP', (compilation) => {
            setTimeout(() => {
                console.log('emit1111')
            }, 1000)
        })
        // tapAsync
        complier.hooks.emit.tapAsync('TestP', (compilation, callBack) => {
            setTimeout(() => {
                console.log('emit222')
                // 执行返回函数
                callBack()
            }, 2000)
        })
        // tapPromise
        complier.hooks.emit.tapPromise('TestP', (compilation) => {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('emit 3333')
                    // 执行返回函数
                    resolve()
                }, 1000)
            })
        })

控制台的结果依旧是同步执行的结果

image.png

make

make从官方文档中看出 make是一个异步并行的钩子,回调方法有一个参数

image.png

配置示例 使用同一注册方法 tapAsync:

  complier.hooks.make.tapAsync('TestP', (compilation, callBack) => {
            setTimeout(() => {
                console.log('make11111')
                // 执行返回函数
                callBack()
            }, 3000)
        })
        complier.hooks.make.tapAsync('TestP', (compilation, callBack) => {
            setTimeout(() => {
                console.log('make2222')
                // 执行返回函数
                callBack()
            }, 1000)
        })
        complier.hooks.make.tapAsync('TestP', (compilation, callBack) => {
            setTimeout(() => {
                console.log('make 3333')
                // 执行返回函数
                callBack()
            }, 2000)
        })

编译的结果是异步执行的结果 打印内容的顺序取决于任务结束的时间

image.png

compilation hooks注册

compilation hooks注册使用的方法与上述complier 钩子注册方法一致。 但是需要注意的是由于webpack流程的执行周期中

微信截图_20221030162222.png

compilation的钩子函数需要在make函数执行之后 注册才能使用

代码示例如下: 如注册事件到 seal

   complier.hooks.make.tapAsync('TestP', (compilation, callBack) => {
            // // seal为异步钩子
            // 在complation 的钩子函数需要在make函数执行之后注册才能使用
            compilation.hooks.seal.tap('TestP', () => {
                console.log('test  seal')
            })
            setTimeout(() => {
                console.log('make 3333')
                // 执行返回函数
                callBack()
            }, 2000)
        })
总结

钩子事件的注册也是严格遵循webpack的流水线工作顺序,不会因为上下文关系的顺序执行不同的事件,刚好又回到了《webpack深入浅出》书中所说的话:“插件需要监听所有与他有关的事,这样才能加入到流水线中去改变生产线的运作