webpack 的整体流程
- 合并参数配置,合并命令行参数和配置文件的参数配置
- 初始化所有插件
- 确定入口,开始初始化
compile
类中的run
方法 - 从入口文件开始递归解析模块,生成模块依赖关系图
- 通过
loader
来解析不同文件内容 - 将所有模块合并成一个或者多个
chunk
- 通过文件系统将
chunk
输出成具体文件
webpack 热更新原理
在启动 webpack-dev-server
的时候也会启动一个 websocket
服务器。同时将websocket
的 runtime
代码注入到 html
中。这样就建立起了一个双向的websocket
服务。在编译完成后会通过文件系统的API
监听工作区文件夹,当文件发生改变时,会触发 webpack
的重新编译。给出一个新的 hash
值。通过 websocket
发送给客户端。客户端通过对比本地hash
和 新hash
是否相同。如果不相同则发送一个jsonp
请求参数是 hash
值去请求json
文件。json
文件中描述了这个更新需要更新的 chunk
名以及对应的 hash
值。如果是对应多个 chunk
则需要发多个 jsonp
请求 [chunk]+[hash].hot-update.js
请求对应模块内容然后再通过执行这些内容,移除就缓存的模块,加载新的模块。来做到模块更新
webpack 的 loader 和 plugin 的区别
loader
主要承担模块之间的翻译功能,因为webpack
在设计时只能识别js/json
等文件其他文件就需要对应的loader
来转换成js
文件。plugin
主要承担拓展功能。在打包
期间webpack
会触发一系列的事件,开发者通过监听这些事件来改变输出结果
tree-shaking 原理
tree-shaking
主要通过 ESM
的静态分析实现,通过静态分析就能确定出哪些模块是永远不会执行的,这个效果需要开启 package.json.sideEffects
来开启默认值是 true
,可选值 boolean,[]
。
如果为 true
的话则告诉打包器这些文件都是有副作用的不能删除,也就没有 tree-shaking
效果 如果值是 数组
则表示这些文件会有副作用不能删除,其他的可以删除
值得一提的是 在 Webpack
中没有直接实现 tree-shaking
效果,他会将死代码进行代码注释标记,需要配合 terser/UglifyJS
等压缩代码插件来移除这些死代码。
webpack 打包优化
- 限制
resolve
查找后缀范围 loader
中加上include/exclude
关键字缩小转换的范围- 通过
optimization.splitChunk
合理拆分chunk
- 通过
thread-loader
并行编译 - 合理使用缓存,比如
babel-loader
的缓存以及cache-loader/hard-source-loader
- 使用
external
排除使用cdn
加载的库 - 使用
esbuild-loader/swc-loader
来代替babel-loader
webpack 的 hash、chunkhash 和 contenthash 的区别
聊聊 source-map
Compiler 和 Compilation 的区别
Compiler
代表了整个 Webpack
的环境配置,在启动 Webpack
的时候被创建。
每一次调用 compiler.run
方法都会创建出一个 Compilation
对象,代表一次完整的构建过程,Compilation
对象包含了关于这次编译的所有信息 依赖关系
、结果
等。
Compilation
对象也提供了很多关键时机的回调,以供插件做扩展。