使用 webpack 设置性能预算

Milica Mihajlija
Milica Mihajlija

Webpack 会合并所有导入的文件,并将它们打包到一个或多个输出文件(称为“软件包”)中。捆绑很方便,但随着应用规模的扩大,您的 bundle 也会随之扩大。您需要监控软件包大小,确保它们不会变得过大,以免影响应用的加载时间。Webpack 支持根据资源大小设置性能预算,并且可以为您密切关注软件包大小。

为了让您了解它的实际效果,我们提供了一个应用示例,该应用会计算距离新年还剩多少天。 它使用 Reactmoment.js 构建而成。 (就像越来越依赖框架和库的实际应用一样。😉)

一款用于计算距离新年还有多少天的应用

测量

此 Codelab 已包含与 Webpack 捆绑的应用。

  1. 点击 Remix to Edit 使项目可供修改。
  2. 点击终端(注意:如果未显示“终端”按钮,您可能需要使用全屏选项)。
  3. 如需获取按颜色编码的资源及其大小列表,请在控制台中输入 webpack
webpack

主软件包以黄色突出显示,因为它大于 244 KiB (250 KB)。

Webpack 输出,显示了 323 KiB 的软件包大小
Webpack 警告您 JS 软件包过大 ⚠️

这些警告在生产模式下默认处于启用状态,默认阈值为244 KiB(未压缩),适用于资源和入口点(在网页初始加载期间使用的所有资源的组合)。

Webpack 警告,指出资源超出了建议的大小限制
Webpack 警告您 JS 软件包过大 ⚠️

Webpack 不仅会向您发出警告,还会提供有关如何缩小软件包的建议。如需详细了解推荐的技术,请参阅网站开发基础

Webpack 性能优化建议
Webpack 性能优化建议 💁

设置自定义效果预算

合适的性能预算取决于项目的性质。最好还是自行研究。一个不错的经验法则是提供小于 170 KB 的压缩/精简关键路径资源。

对于这个简单的演示,不妨尝试更加保守的做法,将预算设置为 100 KB (97.7 KiB)。在 webpack.config.js 中添加以下代码:

module.exports = {
  //...
  performance: {
    maxAssetSize: 100000,
    maxEntrypointSize: 100000,
    hints: "warning"
  }
};

新的性能预算以字节为单位设置:

  • 单个素材资源的字节数上限 (maxAssetSize) 为 100000 字节
  • 入口点为 100000 字节 (maxEntrypointSize)

在这种情况下,只有一个软件包,它也充当入口点。

提示的可能值包括:

  1. warning(默认值):显示黄色警告消息,但 build 通过。最好在开发环境中使用此功能。
  2. error:显示红色错误消息,但 build 仍会通过。建议将此设置用于生产 build。
  3. false:不显示任何警告或错误。
以红色字体显示的 Webpack 性能错误
Webpack 性能提示“错误”🚨

优化

性能预算的目的是在性能问题变得难以修复之前向您发出警告。构建应用的方式不止一种,有些技术可以缩短加载时间。(其中许多都记录在优化 JavaScript 中。🤓)

框架和库让开发者的工作更轻松,但最终用户并不真正关心应用的构建方式,只关心应用是否实用且快速。如果您发现自己超出了性能预算,就该考虑进行可能的优化了。

在实际应用中,大型客户端框架通常很难替换,因此明智地使用它们非常重要。稍加研究,您通常就能找到热门库的替代方案,这些替代方案规模较小,但功能同样强大(date-fnsmoment.js 的一个不错的替代方案)。如果框架或库对性能有显著影响,有时完全不使用它们会更有意义。

移除未使用的代码是优化包含大型第三方库的应用的好方法。“移除未使用的代码”指南详细介绍了此流程,下面提供了一种无需使用 moment.js 即可快速重写倒计时代码的方法。

app/components/Countdown.jsx 中,移除:

const today = moment();
const yearEnd = moment().endOf('year');
const daysLeft = yearEnd.diff(today, 'days');

并删除此行:

const moment = require('moment');

这需要一些数学知识,但您可以使用纯 JavaScript 实现相同的倒计时:

const today = new Date();
const year = today.getFullYear();
const yearEnd = new Date(year,11,31); //months are zero indexed in JS
const timeDiff = Math.abs(yearEnd.getTime() - today.getTime());
const daysLeft = Math.ceil(timeDiff / (1000 * 3600 * 24));

现在,从 package.json 中移除 moment.js,然后在控制台中再次运行 webpack 以构建优化后的软件包。

搞定!您已节省 223 KiB (230KB),应用大小未超出预算。🎉

优化后的 Webpack 软件包大小输出为 97.7 KiB

监控

在 webpack 中设置性能预算只需几行代码,如果您(意外)添加了大型依赖项,系统会向您发出警告。俗话说“眼不见,心不烦”,但 webpack 可以确保您始终了解性能影响。