Skip to content

webpack 基础流程

核心构建流程

初始化

  • 初始化参数:从配置文件、配置对象、shell脚本中读取配置参数,与默认配置合并出最终配置
  • 创建编译器对象:基于最终配置创建compiler对象
  • 初始化编译环境:注入内置插件、注册各种模块工厂、初始化 RuleSet 集合、加载配置的插件等
  • 开始编译:执行compiler对象的run方法
  • 循环遍历入口:根据配置的entry找出所有的入口文件,调用compilition.addEntry将入口文件转换为dependence对象,也就是依赖关系。

开始构建

  • make执行编译:根据entry对应的dependence创建module对象,然后调用loader将模块转译为标准的js,再调用js解释器将内容转换为ast对象,从中找出该模块的依赖模块,然后在递归编译直到所有依赖文件都经过此步骤处理
  • 完成模块编译:上一步递归编译处理得到他们之间的依赖关系,构造出一个依赖关系图

打包输出

  • 输出资源( seal ):根据入口和模块之间的依赖关系,组合成包含多个模块的 Chunk ,再把每个 Chunk 转换成单独的文件加入到输出列表,这里是可以修改输出内容的最后一步
  • 写入文件到磁盘:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件写入到文件系统

以上就是从一个宏观的角度看一次构建的主流程和相关步骤,下面对名词做个简单的介绍

- entry:编译的入口,起点

  • Compiler:编译管理器,webpack 启动之后会创建 compiler 对象,这个对象全局只存在一个,一直到整个构建任务结束为止。
  • Compilation:单次编辑过程的管理器,比如:watch=true 时,每次的文件内容变更触发重新编译时。都会创建一个新的这个对象
  • Depenence:依赖对象,webpack 基于这个寻找依赖关系,转换关系图
  • Module:一切接模块,所有内容的操作都是基于模块的,是 webpack 的基本单位
  • Chunk:由 module 打包组成的产物
  • Loader:资源转换器,因为 webpack 只认识 js 模块
  • Plugin:在打包过程中的扩展功能,让打包流程能做更多事情。

流程详解

初始化阶段

  • process.argswebpack.config.js 合并成为用户配置
  • 调用 validateSchema 对配置经行校验
  • getNormalizedWebpackOptions + applyWebpackOptionsBaseDefaults 合并出最终配置
  • 创建 compiler 对象
  • 遍历用户的 plugins 集合数组,执行插件的 apply 方法来执行插件
  • 调用 new WebpackOptionsApply().process 方法,加载各种内置插件

主要是 WebpackOptionsApply 类,会自动执行 webpack 内置的各种插件,并会在初始化阶段根据配置内容动态注入对应的插件:

  • 注入 EntryOptionPlugin 插件,处理 entry 配置
  • 根据 devtool 值判断用什么插件处理 sourcemap,可选的插件有:EvalSourceMapDevToolPlugin、SourceMapDevToolPlugin、EvalDevToolModulePlugin
  • 注入 RuntimePlugin,根据代码内容动态注入 webpack 运行时

这样 compiler 实例就被创建出来了,环境参数也设置好了,接着就是调用 compiler.compile 函数

js
// 取自 webpack/lib/compiler.js
compile(callback) {
    const params = this.newCompilationParams();
    this.hooks.beforeCompile.callAsync(params, err => {
      // ...
      const compilation = this.newCompilation(params);
      this.hooks.make.callAsync(compilation, err => {
        // ...
        this.hooks.finishMake.callAsync(compilation, err => {
          // ...
          process.nextTick(() => {
            compilation.finish(err => {
              compilation.seal(err => {...});
            });
          });
        });
      });
    });
  }

如有转载或 CV 的请标注本站原文地址