- Loader vs Plugin
- Loader 用于加载并解析各类文件,如 css / sass / ts / markdown / png 等;
- Plugin 用于扩展 Webpack 的能力,实现各种 webpack 本身并不具备的功能,比如清理文件,代码压缩等;
- 常用 Loader
- babel-loader / ts-loader / vue-loader:将各类 js-like 文件解析为 js;
- sass-loader / less-loader / css-loader / style-loader:解析各类样式文件;
- file-loader: 文件批处理;
- url-loader:将文件内容转换为 data-url;
- 常用 Plugin
- HtmlWebpackPlugin 生成 HTML 并自动注入 css 和 js,webpack 5 通过
output.clean: true
代替; - MiniCssExtractPlugin 从 js 中分离 css 并生成单独文件;
- SplitChunksPlugin 自动分割 multi-entry 文件之间的共享模块(内置插件);
- OptimizeCssAssetsWebpackPlugin 压缩 css;
- CompressionWebpackPlugin 压缩 js;
- CleanWebpackPlugin 清理文件;
- CopyWebpackPlugin 复制文件;
- BundleAnalyzerPlugin 可视化构建结果分析;
- HotModuleReplacementPlugin 启动 HMR;
- 代码分割
- Multiple entry + SplitChunksPlugin
- ES6 新语法 Dynamic import
配置多个入口时,要手动声明公共模块,通过 dependOn 标记入口之间的依赖关系,避免将公共依赖重复打包到每个入口文件中(依赖重复)。
SplitChunksPlugin 是 webpack 内置模块,通过以下选项配置:
1 | { |
注意,分离代码并非粒度越细越好,因为粒度越细,则 bundles 越多,在 http2 没有普及之前,每个 bundle 都意味着一个独立的 tcp 连接,大量的 tcp 连接也会成为性能瓶颈。可通过以下属性精细化控制代码分割粒度:
- chunks:指定哪些类型的 chunk 参与拆分(如 ‘initial’、’async’、’all’)。
- minSize:指定一个模块的最小体积,只有超过这个体积的模块才会被拆分。
- minChunks:指定一个模块被引用的最小次数,只有被引用次数超过这个值的模块才会被拆分。
- maxAsyncRequests:指定按需加载的 chunk 的最大数量。
- maxInitialRequests:指定初始加载的 chunk 的最大数量。
- cacheGroups:允许你自定义规则来匹配模块并将其拆分到指定的组中。
注:initial 指 entry 中声明的模块,async 指异步加载模块(如动态 import);
- 本地缓存
Loader 输出结果缓存:
1 | { |
构建结果缓存分为两种——memory 和 filesystem,区别如下:
- memory:输出资源放入内存,是默认行为,速度更快,但内存容量一般较小,适合小项目;
- filesystem:输出资源放入文件系统中,可以理解为放硬盘上,速度略慢,但可以跨多次构建复用,且硬盘空间较大,因此适合大型项目;
1 | { |
通过以下属性精细化控制 cache:
- cacheDirectory:指定 filesystem 类型的缓存结果的存放目录;
- version:静态指定缓存结果版本号,版本改变,则重新构建;
- buildDependencies.config:指定一个依赖数组,内部元素改变时将重新构建;
- buildDependencies.webpack:指定 webpack 依赖版本,版本改变时重新构建;
- 长效缓存
目标:通过浏览器缓存策略提高模块加载速度;
第一步,设置唯一文件名:
1 | { |
第二步,提取 runtime 和 manifest:
1 | { |
第三步,提取很少改变的外部依赖,并改用稳定的 moduleId 生成方式:
1 | { |
- SPA 场景下的 HTTP 缓存策略
首先,入口 HTML 文件必须禁用强缓存:cache-control: no-store;
其次,JS、CSS 文件则可以使用强缓存:
- 每次验证有效性,cache-control:no-cache;
- 有效期内无需验证,除非过期,cache-control:max-age=3600, must-revalidate
此时,假如 JS、CSS 有更新,则基于上文中的构建策略,bundle 文件名将改变,HTML 中对应资源的 URL 也就发生改变,因此会及时响应更新。
当然,JS、CSS 文件也可以使用协商缓存,但需要服务器端进行额外配置(响应条件请求),与之相比,前端通过简单的配置即可实现类似效果,免去与后端开发沟通的过程。