webpack 原理剖析

一、webpack 启动过程分析

1.从webpack命令行说起(此部分可视为进入构建前处理)

通过npm scripts 运行 webpack

  • 开发环境:npm run dev
  • 生产环境:npm run build

webpack运行的两种方式
1)通过 webpack 命令直接运行

  • webpack entry.js bundles.js
    2)通过 package 中的配置的 webpack 命令运行

这个过程发生了什么?
在命令行运行命令后,npm 会让命令行工具进入node_modules.bin目录查找是否存在webpack.sh 或者 webpack.cmd文件,如果存在,就执行,不存在,就抛出错误。
? 在我的项目中实际并未找到这两个文件
!实际入口是:nodel_module\webpack\bin\webpack.js
在这里插入图片描述
启动结果:找到webpack-cli(功能较全) 或者 webpack-commond(轻量化)对应的npm包,并且去执行。

2.webpack-cli 源码剖析

webpack-cli 做的事情:
webpack-cli 提供的不需要编译的命令

const NON_COMPILATION_ARGS = 
["init", //创建一份webpack配置文件
"migrate", //进行webpack版本迁移
"serve", //运行webpack-serve
"generate-loader", //生成webpack loader代码
"generate-plugin", //生成webpack plugin代码
"info" //返回与本地环境相关的一些信息
];

1)引入 yargs,对命令行进行定制,即让我们通过命令行添加参数的形式就可以直接去运行webpack对应的功能。

yargs包简介:
可以通过webpack --help查看webpack提供的命令参数类型
在这里插入图片描述
而这些类型都是来源于文件config-yargs:
在这里插入图片描述
也就是说我们可以直接通过命令行参数的形式对webpack进行配置
在这里插入图片描述
在cli.js中,引入了options选项
convert-argv:就是根据命令行或者webpack配置的一些参数,给options 增加响应的参数以及相应的一些插件。
在这里插入图片描述即调用的是webpack包lib下的webpack.js

二、webpack plugins机制原理解读

我们在使用webpack的时候都知道往plugins中疯狂的加plugin就能让pulgin起作用,那么这些plugins到底是怎么被调用的呢?

简述:webpack可以理解为是一种基于事件流的编程范例,webpack整个流程中定义了很多个事件,而每个plugin就是去订阅这些事件,当整个流程执行到某个事件时,就会去执行每个plugins订阅了该事件的方法。

webpack的核心模块为:compiler、compiltion
在这里插入图片描述
1)Tapable对外提供了同步钩子和异步钩子两类钩子
所有的同步异步钩子都是继承于hook的
在这里插入图片描述
2) 钩子实现的原理:
简述:hook内部维护了一个 taps[]
每次调用tap(同步钩子)时都会往taps中塞一个对应的函数,当调用call时,就会去执行taps中对应的函数方法。
例:

const { SyncHook } = require('tapable');
const hook = new SyncHook(['name']);
hook.tap('hello', (name) => {
    console.log(`hello ${name}`);
});
hook.tap('hello again', (name) => {
    console.log(`hello ${name}, again`);
});

hook.call('ahonn');
// hello ahonn
// hello ahonn, again

实际的细节实现比这个复杂得多,详细剖析见:
https://zhuanlan.zhihu.com/p/79221553

3)那么在webpack中,对于钩子是怎么用的呢?
1.创建钩子的位置:complier的构造函数中
在这里插入图片描述
3.钩子挂载的过程
在这里插入图片描述
3.对各个钩子监听各个钩子函数的调用过程
在complier.run中:最终进行了call的调用
在这里插入图片描述
在这里插入图片描述
1)上图的call方法只被调用了一次,是因为此处传入的params是已经被加工过的,实际还是会根据params的处理情况进行多个钩子监听函数的执行。
2)此时compliation才被创建出来,即就是要处理的钩子函数执行完成后进行的操作。compilation 实例能够访问所有的模块和它们的依赖(大部分是循环依赖)。它会对应用程序的依赖图中所有模块进行字面上的编译(literal compilation)。在编译阶段,模块会被加载(loaded)、封存(sealed)、优化(optimized)、分块(chunked)、哈希(hashed)和重新创建(restored)。

三、webpack 编译流程梳理:

简述:

1.通过loader(loader-runner)去解析模块(对模块的源代码进行转换,将不同的语言(其他资源例如 css,图片,或者其他的语法集比如jsx)转换为js)
2.通过parser,NormalModelFactory中使用的是acorn,作用:

将代码中通过依赖的模块,添加到模块依赖列表中去,这样的就不断的去分析依赖,不断的去构建,将构建结果存到compliation的modules中。
(注:解析依赖模块的时候,通过require引进来的是通过NormalModelFactory解析的,而带路径的模块则是通过ContextMOduleFactory解析的)

3.资源生成(modules->chunks)

什么是modules和chunks
转自:https://www.cnblogs.com/skychx/p/webpack-module-chunk-bundle.html
1)对于一份同逻辑的代码,当我们手写下一个一个的文件,它们无论是 ESM 还是 commonJS 或是 AMD,他们都是 module ;
2)当我们写的 module 源文件传到 webpack 进行打包时,webpack 会根据文件引用关系生成 chunk 文件,webpack 会对这个 chunk 文件进行一些操作;
3)webpack 处理好 chunk 文件后,最后会输出 bundle 文件,这个 bundle 文件包含了经过加载和编译的最终源文件,所以它可以直接在浏览器中运行。

4.优化,执行所有监听seal相关钩子的函数。
5.输出文件到dist目录
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fly_bit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值