打包流程
- 初始化
- 读取config配置
- 创建compiler实例
- 加载插件
- 编译阶段 从入口文件递归解析依赖关系分析,生成依赖图
- 模块处理 通过loader转译,比如balel,sass-loader处理等。
- 输出chunk 将各个依赖文件生成对应的chunk代码块,此时会走插件逻辑。
- 生成文件 根据输出配置filename、path等生成最终的bundle
常用的面试题
Webpack 的 Loader 和 Plugin 有什么区别
- loader: loader的功能是将特定的文件转译成浏览器能识别的js文件。如
babel-loader
、file-loader
- Plugin: 插件,属于是拓展的功能,可以在webpack各个打包流程的生命周期函数中做特殊处理。 如
HtmlWebpackPlugin
、MiniCssExtractPlugin
如何优化 Webpack 构建速度?
优化方案:
- 编译阶段
- 缓存 cache: { type: 'filesystem' }
- 优化loader作用范围 :比如使用exclude,精确loader作用范围,以提高效率。
- 开发阶段
- 代码分割 treehShaking 等
- 开启多线程等:happyPack
- 压缩代码体积
- 比如图片给一个maxSize
js
{
test: /\.(jpe?g|png|svg|gif)$/i,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 25 * 1024, // 25kb
},
},
generator: {
filename: "assets/imgs/[name].[hash:8][ext]",
},
},
什么是 Tree Shaking?如何生效?
package.json 配置 sideEffects:false;会将没有使用的代码去掉 treeshaking的限制:只支持esm语法。
js
// 原始代码(问题:全量引入lodash)
import _ from 'lodash';
export const deepClone = (obj) => _.cloneDeep(obj);
// 优化后(按需引入 + 纯函数标记)
import { cloneDeep } from 'lodash-es';
export const deepClone = /*#__PURE__*/ (obj) => cloneDeep(obj);
如何实现按需加载(懒加载)?
使用动态导入的方法