打通webpack任督二脉
一、基础梳理(上帝视角de灵魂拷问)
1.1 webpack是什么?
webpack就是一个js的翻译器- 它只认识
import
这样的语句,其他高级js
语法,一概不认。
- 它只认识
核心定义:模块打包工具 👏👏👏
- 识别
import
,引入import
模块,打包生成最终的模块。
1.2 什么是webpack模块
1.3 webpack.config.js的作用是什么?
扩展webpack
的能力,提供给webpack
使用,webpack
会默认读取webpack.config.js
的信息。
1.4 Loader是什么?
我的理解:它就是一个对于特定文件所提供给webpack
打包的一种打包方案。
stackoverflow Reference https://stackoverflow.com/a/46176755/7552246
Loaders
Loaders work at the individual file level during or before the bundle is generated.
在bundle
生成期间或之前,loader
在单个文件级别工作。
Plugins
Plugins work at bundle or chunk level and usually work at the end of the bundle generation process. Plugins can also modify how the bundles themselves are created. Plugins have more powerful control than loaders.plugin
在bundle
或chunk
级别工作,通常在bundle
生成结束时工作。插件还可以修改bundle
本身的创建方式。plugin
具有比loader
更强大的控制功能。
准备工作
- 什么是AST?
AST(Abstract Syntax Tree),
- AST在JS代码执行的那个阶段产生?
词法分析–>语法分析(生成AST)–>预编译–>解释执行
- AST语法树
1 | type: 描述该语句的类型 --> 变量声明的语句 |
基础配置优化
利用好
webpack.config.js
配置中的resolve
,主动告诉webpack
,我们需要对于哪些文件进行一个打包查找:(这里优先介绍常用的)1>
extensions
,告诉webpack
,我们需要优先查找哪些没有后缀名但是拥有前缀名
的文件,列在数组首位的后缀名优先。2>
alias
设置别名路径,当路径过长的时候,可以使用alias
设置短链接指向。在
合适
的场景
,利用好合适
的loader
去处理合适
的文件
,例如可以利用url-loader
去处理图片文件,将图片适当的base64
化。在
loader
中配置exclude
&include
,缩小complier
范围。利用
cache-loader
&cache-plugin
缓存大体量的loader
ORplugin
,实现提效。
分割打包策略
为什么要分包?分什么包?怎么分包?分包可以达到什么效果?
- 为什么要分包?
- 原始的打包会将
node_modules
与需要打包的(src)
文件打包进一个bundle
,在client
进行缓存的时候,重新打包请求,耗费时间,导致首页白屏时间较长,可以选择将需要稳定版本的node_modules
持久缓存起来,经常变化的lib
/src
待编译文件打包进核心的bundle
。
- 原始的打包会将
- 分什么包?
- 可以将稳定版本的
node_modules
分包进一个stable vendor
;可以将需要latest
版本的node_modules
分包进一个lazy vendor
;可以将核心待编译文件分包进main bundle
;可以将测试文件分包进test vendor
,注意需要在main bundle
中exclude
出测试文件
;
- 可以将稳定版本的
- 怎么分包?
webpack 4
之前利用的是SplitChunksPlugin
这个插件,但是4
版本中已被废弃,可以直接在内部通过optimization
进行配置。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31module.exports = {
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
default: {
name: 'common',
chunks: 'initial',
minChunks: 5, //模块被引用5次以上的才抽离
// priority: -1 // 设置优先级
},
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
// 部分模块是以 @ 开头的,直接在分包命名中过滤掉
return `npm.vendor.${packageName.replace('@', '')}`;
},
},
testModule: {
chunks: 'all',
test: /__test__\/*/,
name: 'test.vendor' ,
}
},
}
},
}
- 分包可以达到什么效果?
缓存优化构建策略
happypack
,之前有提到这个工具,但是其作者已经不维护了,另外多进程打包考验cpu
能力,核数越高,打包越快,所以一般可能很难见成效;cache-loader
、cache-plugin
可以很好的缓存那些大体量的loader
或者plugin
编译的结果在disk
内存中,下次编译的时候可以直接从disk
中拿。如果在服务端也可以在放置在redis
中。HardSourceWebpackPlugin
可以实现持久缓存,第一次构建可能效果不明显,第一次之后,效果可以实现提升。
怎么理解chunk
、bundle
?
如上图,其实还是很好理解的:
module
是打包前的引入文件,chunk
是打包时的处理文件,bundle
是webpack
处理chunk
的产物。
chunk
的数目怎么计算?很好识别的:一个入口文件一个chunk
,一个分包策略一个chunk
。
webpack
的构建流程是怎样的呢?
合并
shell
参数与webpack.config.js
中的配置。在
config
配置文件中去确定entry
入口。开始执行
run
编译,对应文件使用对应file-loader
,递归处理模块。根据入口与代码分割方案生成
chunk
。处理
chunk
,生成最终的bundle
。输出完成。