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 对象也提供了很多关键时机的回调,以供插件做扩展。