概述 Webpack 的运行机制,不会讲解如何配置或者使用 Webpack。
在了解 Webpack 原理前,需要掌握以下几个核心概念,以方便后面的理解:
简单来说,Webpack 的构建流程可以分为以下三大阶段:
这是一个串行的过程,从启动到结束分为好几个阶段,每个阶段会发生很多的事件,Webpack 会把这些事件广播出来,所谓的 Plugin 就是在监听到特定的事件后执行相关代码,这期间插件还可以调用 Webpack 提供的 API 来改变 Webpack 的运行结果。
详细的步骤我们参照下图来说:
注:图中并未展示所有事件,可参考 Webpack 文档。图片来源见文末。
这个阶段 webpack 会将用户配置的 webpack.config.js
和 shell
脚本传过来的参数整合成 options
对象传到了下一个流程的控制对象中。合并参数过程中 webpack 也会根据参数中的信息来执行插件实例化语句new Plugin()
。
js// options 作为最后返回结果,包含了之后构建阶段所需的重要信息。
{
entry: {},//入口配置
output: {}, //输出配置
plugins: [], //插件集合(配置文件 + shell指令)
module: { loaders: [ [Object] ] }, //模块配置
context: //工程路径
...
}
用上一步得到的参数初始化 Compiler 实例,Compiler 负责文件监听和启动编译。Compiler 实例中包含了完整的 Webpack 配置,且全局只有一个 Compiler 实例。这个时候,真正的 webpack 对象才刚被初始化,具体的初始化逻辑在 lib/webpack.js
中:
jsfunction webpack(options) {
var compiler = new Compiler();
...// 检查 options,若 watch 字段为 true,则开启 watch 线程
return compiler;
}
...
有了 Compiler 实例之后,开始加载插件,依次调用插件的 apply 方法,让插件可以监听后续的所有事件节点。同时给插件传入 compiler 实例的引用,以方便插件通过 compiler 调用 Webpack 提供的 API。
遍历配置文件中所有入口,为每个 Entry 实例化一个对应的 EntryPlugin,为后面该 Entry 的递归解析工作做准备。
调用完所有内置的和配置的插件的 apply 方法。
根据配置初始化完 resolver,resolver 负责在文件系统中寻找指定路径的文件。
webpack 的实际入口是 Compiler 中的 run 方法,run 一旦执行后,就开始了编译和构建流程 ,其中有几个比较关键的 webpack 事件节点。
compiler.run
后首先会触发 compile 事件 ,这一步会构建出 Compilation 对象。
当 Webpack 以开发模式运行时,每当检测到文件变化,一次新的 Compilation 将被创建。一个 Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等。这个对象有两个作用,一是负责组织整个打包过程,包含了每个构建环节及输出环节所对应的方法,在每一个节点都会触发 webpack 事件去调用各插件。二是该对象内部存放着所有 module ,chunk,生成的 asset 以及用来生成最后打包文件的 template 的信息。
在编译阶段中,最重要的要数 compilation 事件了,因为在 compilation 阶段调用了 Loader 完成了每个模块的转换操作,在 compilation 阶段又包括很多小的事件,它们分别是:
build-module:使用对应的 Loader 去转换一个模块。 normal-module-loader:在用 Loader 对一个模块转换完后,使用 acorn 解析转换后的内容,输出对应的抽象语法树(AST),以方便 Webpack -后面对代码的分析。 program:从配置的入口模块开始,分析其 AST,当遇到 require 等导入其它模块语句时,便将其加入到依赖的模块列表,同时对新找出的依赖模块递归分析,最终搞清所有模块的依赖关系。 seal:所有模块及其依赖的模块都通过 Loader 转换完成后,根据依赖关系开始生成 Chunk。
要详细的把 Webpack 的整个流程说下来,一篇文章肯定是不够的。这篇文章只是大概的梳理了一下,讲的很粗糙,后续有了新的理解还会更新。作者水平有限,还请轻喷~
本文作者:青波
本文链接:https://zhaozhaobijiben.com/post/50
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
预览: