Webpack-源码二,整体调用流程与Tapable事件流

本文深入分析Webpack的整体调用流程,从shell输入webpack命令开始,揭示了命令执行过程、参数整合、开始编译打包的步骤。接着探讨了Tapable事件流,详细列举了webpack中的关键事件及其在打包过程中的触发顺序。文章还介绍了Tapable类中事件监听者的执行顺序,包括applyPluginsAsync、applyPluginsParallel和applyPluginsWaterfall方法,帮助理解plugin的执行策略。通过对这些概念的理解,为后续分析plugin和loader的源码打下基础。

上一篇博客中分析了webpack打包以后的bundle文件,了解webpack是如何通过require模拟commonjs标准加载模块的。下面探索webpack整体调用的流程,也就是如何通过shell输入webpack命令就可以实现整个编译、打包过程的。该系列博客的所有测试代码

这篇博客只对整个流程及相关的事件流进行分析,不具体分析每个步骤中的具体实现。也就是,对于plugin和loader的具体分析请移步后面的博客。

整体调用流程

只有了解整体流程以后,才更容易找到你关心功能的源码。比如,如果你想知道plugin的工作原理,面对webpack的庞大源码,很难找到到底哪些js文件与plugin相关。于是我想先了解整体流程。

思路

捋顺流程的思路很简单,首先找到node_modules/.bin/webpack.cmd查看webpack命令干了什么:

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\..\webpack\bin\webpack.js" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\..\webpack\bin\webpack.js" %*
)

在安装node的情况下,会执行webpack/bin/wepack.js,下面看看这个文件进行了哪些操作。

  • 通过[yargs](https://www.npmjs.com/package/yargs)获得shell中的参数
  • webpack.config.js中的参数和shell参数整合到options对象上
  • 调用lib/webpack.js开始编译和打包

依照这个思路继续查看lib/webpack.js。不再一步一步仔细分析,下面直接展示分析后的结果。

流程

下图展示了webpack主要流程涉及的类及其调用关系。
这里写图片描述

  • lib/webpack.js中返回一个compiler对象,并调用了compiler.run()

  • lib/Compiler.js中,run方法触发了before-runrun两个事件,然后通过readRecords读取文件,通过compile进行打包,打包后触发before-compilecompilemake等事件;compile是主要流程,该方法中实例化了一个Compilation类,并调用了其finishseal方法,图中没有展开compile方法具体代码

  • lib/Compilation.js中定义了finishseal方法,还有一个重要方法addEntry。这个方法通过调用其私有方法_addModuleChain完成了两件事:根据模块的类型获取对应的模块工厂并创建模块;构建模块

  • lib/Compiler.js中没有显式调用addEntry,而是触发make事件,lib/DllEntryPlugin.js为一个监听make事件的插件,在回调函数中调用了addEntry

具体分析_addModuleChain,其完成的第二件事构建模块又可以分为三部分:

  • 调用loader处理模块之间的依赖
  • loader处理后的文件通过[acorn](https://github.com/ternjs/acorn)抽象成抽象语法树AST
  • 遍历AST,构建该模块的所有依赖

至此,我们知道了,plugin是通过事件监听的方式实现(DllEntryPlugin.js就是一个插件);loader相关源码可以从_addModuleChain为切入点看。

但是,我们多了几个疑惑:webpack到底有哪些事件(些plugin时候需要),这些事件流是如何控制的,每个事件都在什么阶段触发?

Tapable事件流

由第一部分分析可以知道,webpack整个流程是用事件进行控制的,也就是,不同的功能函数都封装到plugin中,plugin相当于listener,主打包流程中调用各种apply方法(如:applyPluginsAsync等)触发pluginapply方法相当于emitter。该流程通过Tapable类进行控制,上部分中 CompilerCompilation两类都继承自Tapable。那么,到底webpack中到底有哪些事件,不同的apply方法具体行为有什么不一样呢?

webpack中的事件

webpack中的事件如下,这些事件出现的顺序固定,但不一定每次打包所有事件都触发:

类型 名字 事件名
[C] applyPluginsBailResult entry-option
[A] applyPlugins after-plugins
[A] applyPlugins after-resolvers
[A] applyPlugins environment
[A] applyPlugins after-environment
[D] applyPluginsAsyncSeries run
[A] applyPlugins normal-module-factory
[A] applyPlugins context-module-factory
[A] applyPlugins compile
[A] applyPlugins this-compilation
[A] applyPlugins compilation
[F] applyPlu
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值