webpack 的作用是根据入口文件将源代码编译(构建、打包)成最终代码。中间经过webpack打包,打包的过程就是编译
整个过程大致分为三个步骤:初始化
、编译(最重要)
、输出
「初始化」
在初始化这个阶段webpack会将CLI参数
、配置文件
、默认配置
进行融合,形成一个最终的配置对象。
CLI参数:使用命令行工具,可能会加一些参数进去,比如:
npx webpack --mode=development --config xxx
配置文件:webpack.config.js
文件里面的配置
默认配置:比如入口entry,默认为 ./src/index.js
对配置的处理过程是依托一个第三方库yargs完成的,yargs库就是融合配置的。初始化阶段相对比较简单,主要是为接下来的编译阶段做必要的准备。目前,可以简单的理解为:初始化阶段主要用于产生一个最终的配置。
「编译」
chunk
是webpack在内部构建过程中的一个概念,译为块
,它表示通过某个入口找到的所有依赖的统称,比方说:入口模块(./src/index.js)依赖a模块(./src/a.js),a模块又依赖b模块(./src/b.js),通过一个入口模块分析依赖关系,可以找到三个模块,那么index.js
、a.js
、b.js
这三个统称为一个chunk
根据入口模块(默认为./src/index.js)创建一个chunk,每一个chunk是有名字的,意味着chunk有可能也会有多个,入口文件是可以有多个的。
默认情况下只有一个chunk,每个chunk都有至少两个属性:
name:默认为main
id:唯一编号,如果是开发环境,那么id和name相同,如果是生产环境,则是一个数字,从0开始。
我们先通过下面代码来简单过一遍这个图:
代码:
//模块名:
./src/index.js (未加载状态)
//模块内容:
console.log("index");
require("./a");
require("./b");
./src/index.js
,它会通过这个路径检查当前这个模块是否已经加载过,注意哦:它不是运行模块,而是瞅一眼,看看模块记录表(上图右边蓝色表格)中该模块是不是被加载过,首次检查表格是没有内容的,空的。检查 ./src/index.js 模块,发现该模块并未加载过
//读取内容(字符串)
console.log("index");
require("./a");
require("./b");
require("./a");
require("./b");
AST在线测试工具:https://astexplorer.net/
//记录依赖
["./src/a.js","./src/b.js"]
require
改为_webpack_require
,将依赖的模块
改为模块id
console.log("index");
_webpack_require("./src/a.js");
_webpack_require("./src/b.js");
以上就是webpack编译过程,做这一切最终的目的就是形成一个模块记录表。
下面有个简图,经过上述编译过程之后会在chunk中通过入口文件加载形成多个模块,每个模块记录了转换之后的代码。
在第二步完成后,chunk中会产生一个模块列表,列表中包含了模块id
和模块转换后的代码
。接下来,webpack会根据配置为chunk生成一个资源列表,即chunk assets
,资源列表可以理解为是生成到最终文件的文件名和文件内容。
chunk hash是根据所有chunk assets的内容生成的一个hash字符串
hash:一种算法,具体有很多分类,特点是将一个任意长度的字符串转换为一个固定长度的字符串,而且可以保证原始内容不变,产生的hash字符串就不变。
简图:
将多个chunk的assets合并到一起,并产生一个总的hash
「输出 emit」
webpack将利用node中的fs模块(文件处理模块),根据编译产生的总的assets,生成相应的文件。
「总过程」
当敲下webpack打包命令之后,文件开始初始化,各个参数进行融合,形成一个最终的配置对象,然后把配置对象交给编译器进行编译, 通过入口模块找到互相依赖模块形成模块列表,接下来webpack会根据配置,为chunk生成一个资源列表,然后将每一个chunk生成的资源合并成一个完整的资源,并且生成一个完整的hash值,最终根据完整的资源列表输出到文件。
涉及术语
📌 最后
若本文对于 webpack编译原理
阅读有任何错误的地方,欢迎大家给我提意见,一定虚心听取你们的指正,若觉得不错的,也可以点个🌟「star」 🌟 支持一下我。