揭秘webpack插件工作流程和原理( 二 )

  1. afterEmit:文件已经写入磁盘完成
  2. done:完成编译
奉上一张滴滴云博客的WebPack 编译流程图,不喜欢看文字讲解的可以看流程图理解记忆
WebPack 编译流程图原图出自:https://blog.didiyun.com/index.php/2019/03/01/webpack/
看完之后,如果还是看不懂或者对缕不清webpack构建流程的话,建议通读一下全文,再回来看这段话,相信一定会对webpack构建流程有很更加深刻的理解 。
理解事件流机制 Tapablewebpack本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是Tapable 。
Webpack 的 Tapable 事件流机制保证了插件的有序性,将各个插件串联起来,Webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条webapck机制中,去改变webapck的运作,使得整个系统扩展性良好 。
Tapable也是一个小型的 library,是Webpack的一个核心工具 。类似于node中的events库,核心原理就是一个订阅发布模式 。作用是提供类似的插件接口 。
webpack中最核心的负责编译的Compiler和负责创建bundles的Compilation都是Tapable的实例,可以直接在 Compiler 和 Compilation 对象上广播和监听事件,方法如下:
/*** 广播事件* event-name 为事件名称,注意不要和现有的事件重名*/compiler.apply('event-name',params);compilation.apply('event-name',params);/*** 监听事件*/compiler.plugin('event-name',function(params){});compilation.plugin('event-name', function(params){});Tapable类暴露了tap、tapAsync和tapPromise方法,可以根据钩子的同步/异步方式来选择一个函数注入逻辑 。
tap 同步钩子
compiler.hooks.compile.tap('MyPlugin', params => {  console.log('以同步方式触及 compile 钩子 。')})tapAsync 异步钩子,通过callback回调告诉Webpack异步执行完毕tapPromise 异步钩子,返回一个Promise告诉Webpack异步执行完毕
compiler.hooks.run.tapAsync('MyPlugin', (compiler, callback) => {  console.log('以异步方式触及 run 钩子 。')  callback()})compiler.hooks.run.tapPromise('MyPlugin', compiler => {  return new Promise(resolve => setTimeout(resolve, 1000)).then(() => {    console.log('以具有延迟的异步方式触及 run 钩子')  })})Tabable用法const { SyncHook, SyncBailHook, SyncWaterfallHook, SyncLoopHook, AsyncParallelHook, AsyncParallelBailHook, AsyncSeriesHook, AsyncSeriesBailHook, AsyncSeriesWaterfallHook } = require("tapable");
揭秘webpack插件工作流程和原理

文章插图
 
tapable
简单实现一个 SyncHookclass Hook{    constructor(args){        this.taps = []        this.interceptors = [] // 这个放在后面用        this._args = args     }    tap(name,fn){        this.taps.push({name,fn})    }}class SyncHook extends Hook{    call(name,fn){        try {            this.taps.forEach(tap => tap.fn(name))            fn(null,name)        } catch (error) {            fn(error)        }    }}tapable是如何将webapck/webpack插件关联的?Compiler.js
const { AsyncSeriesHook ,SyncHook } = require("tapable");//创建类class Compiler {    constructor() {        this.hooks = {           run: new AsyncSeriesHook(["compiler"]), //异步钩子           compile: new SyncHook(["params"]),//同步钩子        };    },    run(){      //执行异步钩子      this.hooks.run.callAsync(this, err => {         this.compile(onCompiled);      });    },    compile(){      //执行同步钩子 并传参      this.hooks.compile.call(params);    }}module.exports = Compiler


推荐阅读