CLAYYA

乌贼馋辣鱼的博客

构建流程和原理

2024-11-28

构建流程和原理

Webpack 的核心能力就是静态模块打包能力。Webpack 能够将各种类型的资源 —— 包括图片、音视频、CSS、JavaScript 代码等,通通转译、组合、拼接、生成标准的、能够在不同版本浏览器兼容执行的 JavaScript 代码文件

构建流程

image

1.初始化

  • 初始化参数:从配置文件、 配置对象、Shell 参数中读取,与默认配置结合得出最终的参数;
  • 创建编译器对象 Compiler:用上一步得到的参数创建 Compiler 对象, 其中存储了配置信息,挂载了许多生命周期 hook。
  • 初始化编译环境:包括注入内置插件、注册各种模块工厂、初始化 RuleSet 集合、加载配置的插件等;
  • 开始编译:执行 compiler 对象的 run 方法,创建 Compilation 对象,调用 compiler.compile 方法开始执行构建。
  • 确定入口:根据配置中的 entry 找出所有的入口文件,调用 compilation.addEntry 将入口文件转换为 dependence 对象。把入口文件的绝对路径添加到依赖数组,记录此次编译依赖的模块。

2.构建

  • 编译模块(make) :从 entry 文件开始,调用 loader 将模块转译为标准 JS 内容(如sass转译css、ts转译js等),调用 JS 解析器 Acorn (opens new window)将内容转换为 AST 对象,从中找出该模块依赖的模块,再 递归 处理这些依赖模块,直到所有入口依赖的文件都经过了本步骤的处理;
  • 完成模块编译:上一步递归处理所有能触达到的模块后,得到了每个模块被翻译后的内容以及它们之间的依赖关系图 - ModuleGraph​。构建阶段经历了 module => ast => dependences => module​ 的流转,先将源码解析为 AST 结构,再在 AST 中遍历 import 等模块导入语句,收集模块依赖数组 —— dependences​,最后遍历 dependences​ 数组将 Dependency​ 转换为 Module​ 对象,之后递归处理这些新的 Module​,添加至ModuleGraph​,直到所有项目文件处理完毕。

3.封装

  • 合并(seal) :根据入口和模块之间的依赖关系,模块转译,收集运行时依赖(其实在上一阶段就已经进行了,基于静态代码分析的方式收集运行时依赖),将模块代码与运行时代码合并,组装成一个个包含多个模块的 Chunk;
  • 优化(optimization) :对上述 Chunk 施加一系列优化操作,包括:tree-shaking、terser、scope-hoisting、压缩、Code Split 等;
  • 写入文件系统(emitAssets) :在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统,生成 Bundle IIFE。