介绍
在过去的 15 年里,JavaScript 生态系统迅速扩展,引入了无数工具使开发变得更加容易。但这些工具是有代价的:增加捆绑包的大小。事实上,HTTP Archive 的数据显示,每页平均传输的 JavaScript 量已从 2010 年的 90 KB 激增至 2024 年的 650 KB(来源)。
尽管压缩技术的采用率不断提高并且取得了进步,但这一趋势并没有显示出放缓的迹象。随着我们不断添加功能,挑战仍然存在:我们如何才能减少 JavaScript 的数量?
奇怪的是,解决方案既简单又困难。最简单的部分是项目级别的调整,可以快速取得成果。困难的部分是产生持久的影响,这需要社区范围内的改变来改进捆绑器、库和工具。
本文重点关注您的项目的可行改进,涵盖:
- 捆绑器:优化构建工具以减少输出大小。
- 库:明智地选择和使用外部依赖项。
- 您的项目:缩小捆绑包的实用步骤。
未来的文章将讨论我们可以做出的生态系统范围内的改进,但现在,让我们解决这些因素如何导致捆绑包膨胀 - 以及如何管理它们。
为什么优化 JavaScript 很重要
JavaScript 是现代网络交互背后的引擎,但它不是免费的。 JavaScript 是浏览器必须处理的计算成本最高的资源。它通常是决定页面感觉快还是慢的瓶颈,因为臃肿的包会阻止渲染并降低整体性能。
JavaScript 包越大,加载、解析、编译和运行所需的时间就越长。这会延迟其他一切 - 例如显示内容或让用户与页面交互。对于使用具有光纤连接的高端笔记本电脑的人来说,这可能是一个小烦恼。但对于使用低功率手机或不稳定网络的人来说,这可能是完全留在或离开您的网站的区别。
减少 JavaScript 包大小的第一步是 Tree Shaking(或“死代码消除”),大多数捆绑器都是开箱即用的。但所有捆绑商都是平等的吗?
捆绑者
JavaScript 中的捆绑已经取得了长足的进步——从手动串联和任务运行器到复杂的捆绑器。如今,捆绑器性能是一个关键焦点,开发人员优先考虑更快的构建。然而,构建速度并不是一切。同样重要的是它们生成的捆绑包的大小,因为较小的捆绑包意味着用户的加载时间更快。
为了寻求更好的性能,我们已经从使用 JavaScript 编写捆绑器转向 Rust 和 Go 等语言。此切换需要从头开始编写它们,因此旧捆绑器中存在的每个功能和优化都必须重新实现。从长远来看,这可能会得到回报。然而,从短期来看,这意味着它们缺少 JavaScript 捆绑器多年来开发的一些功能,例如良好的 tree shake。这正是可以帮助我们最小化捆绑包大小的功能。
基准
当然,空谈是廉价的,所以让我们看看数字,好吗?
让我们比较八个流行的库,并将它们与七个流行的捆绑器捆绑在一起。为了保持公平,我使用了:
- 节点 22.12.0
- 自我报告的构建时间
- 第三次运行计时,让缓存预热,特别是对于像 Parcel 这样的工具
- 删除所有注释(包括许可证)的配置,因为捆绑程序以不同的方式处理它们
您可以查看基准设置存储库以获取确切的配置。
经过测试的捆绑器:
- esbuild (0.24.0)
- 包裹(2.13.2)
- 滚动(0.15.0-snapshot-993c4a1-20241205003858)
- 汇总 (4.28.0)
- Rspack (1.1.5)
- Vite (6.0.3)
- webpack (5.97.1)
请注意,在撰写本文时,Rolldown 仍处于 alpha 阶段,因此它处于劣势,随着时间的推移,其结果可能会有所改善。
测试过的库:
- chart.js
- ckeditor5
- d3
- 手工表
- 勒克森
- mobx
- tippy.js
- 佐德
这些库的大小和功能各不相同 - 有些库几乎可以像独立应用程序一样运行。
构建速度
让我们从构建速度开始,因为这是开发人员似乎非常关心的事情。将所有这些库捆绑在一起时,esbuild 是获胜者,其构建时间为 192 毫秒。与最慢的构建时间 7.23 秒相比,快了 37 倍以上。
根据这些结果,我们可以将捆绑器分为三类:
- 极快™:esbuild、Parcel、Rolldown(
- 更快:Rspack(2.2 秒)。
- 慢:Rollup、Vite、webpack(每个 5 秒)。
差异非常明显。例如,Rolldown 和 Rspack 分别比旧版本 Rollup 和 webpack 快 11.5 倍和 3.3 倍,同时保持理论上的向后兼容性。切换到这些较新的捆绑器可以显着提高大型项目的生产力。
输出尺寸
就输出大小而言,差异并不像构建时间那么大,但它们仍然很重要。
汇总结果
将所有八个库捆绑在一起时,Vite 是获胜者,输出大小为 2087 KiB。与最大输出大小 2576 KiB 相比,输出小了 23.5% 以上。
输出大小的 23.5% 差异是巨大的:在较慢的 3G 连接下,最小的包可能需要大约 5.7 秒才能下载,而最大的包可能需要大约 7 秒。解析和执行时间也会随着包的大小而变化,因此现实世界的差异可能更加明显。
根据这些结果,我们可以将捆绑器输出再次分为三类:
- 最小:esbuild、Parcel、Rollup 和 Vite (~2085–2160KiB)。
- 好的:webpack (~2317KiB)。
- 大:Rolldown,Rspack (~2490–2580KiB)。
个别图书馆
聚合结果并不能描绘出全貌,因为您不太可能在项目中使用上面列出的所有库。更有趣的是这些捆绑器如何处理各个库。
对于像chart.js和mobx这样的库,捆绑器的选择会极大地影响输出大小,差异达到70%。这凸显了使用特定依赖项测试捆绑器的重要性。在大多数其他情况下,差异要小得多,约为 20-30%。
此外,虽然 webpack 总体排名居中,但在 8 个案例中,有 6 个案例表现最好。然而,由于在捆绑handsontable和chart.js时它的表现要差得多,所以它最终还是这样。这意味着,根据您使用的库,webpack 可能是一个不错的选择。
另一方面,我们有 Rolldown。它在 8 个案例中的 7 个中表现最差(请记住,它仍处于 alpha 状态)。
Rspack 也是一个类似的故事。虽然它的性能比 Rolldown 更好,但它仍然生成了比其他捆绑器大得多的捆绑包。
如果您正在考虑迁移到较新的捆绑程序,使用您使用的库进行测试,看看更快的构建速度是否不会以增加输出大小为代价。
捆绑尺寸与输出速度
如图所示,较新的捆绑器速度更快,但可能会生成更大的捆绑包。从较旧的捆绑程序迁移时,不仅要比较构建时间,还要比较生成的捆绑包大小。您可能会发现自己用更快的构建来换取更大的捆绑包。
例如,在 Angular 从 webpack 切换到 esbuild 后,一些开发人员报告说,空的 Angular 应用程序的大小增加了约 20KB。这完美地突出了构建速度与捆绑包大小的权衡。
这并不是说您不应该关注构建速度,因为它对于开发人员的生产力和幸福感很重要。 CI 构建时间和合并代码所需的时间之间也存在相关性。
选择捆绑器时,首先查看它提供的功能。然后目标是构建速度和包大小之间的平衡。选择可以在您方便的时间内生产尽可能最小的捆绑包的捆绑商。
测试项目中的一些代表性库。如果您的依赖项构成了代码库的大部分,那么您在这些基准测试中看到的差异可以很好地预测您的情况。
图书馆
我们列表中的下一个是外部库,它们通常构成 JavaScript 包的大部分。在我开发过的许多(如果不是大多数)应用程序中,它们占据了捆绑包大小的大部分。这就是为什么明智地选择(和使用)它们如此重要。
黄金但旧
我们中的许多人都安装了 lodash、axios 或 moment 等库,只是为了使用单个功能 - 导致应用程序臃肿。这些库很棒并且具有重要的历史意义,但随着它们变得越来越流行,更轻的替代品被创建,并且它们的一些功能被添加到语言本身中。
我们可以利用这一点。我可以列出这些库的本机 API 或更新且更小的替代方案,但已经有很多文章对此进行了介绍。还有很多其他库,不可能全部涵盖。
这就是为什么我只会给你一个一般性建议,让你看看你使用的库,看看是否可以删除它们或用本机 API 或更小的替代品替换它们。您可能不需要 * 网站是一个很好的入门资源。
优化安装路径
默认情况下,大多数库并未针对大小进行优化,但有些库提供特殊的安装路径或部分构建。即使在我们测试的库中,chart.js、handsontable 和 ckeditor5 也提供了一种通过仅包含您需要的部分来减小库大小的方法。让我们以 ckeditor5 为例。
默认安装路径导致捆绑包大小在 660 到 800 KiB 之间。但是,如果我们使用优化的安装路径,捆绑包大小会下降到 603-653 KiB,仅 Rolldown 生成的捆绑包大小约为 750 KiB。大小减少了 7% 到 23%,具体取决于捆绑程序。
重复的依赖项
另一件事要注意的是重复的依赖关系。这是 JavaScript 应用程序中一个令人惊讶的常见问题。例如,Bluesky 嵌入小部件有两个版本的 zod 验证库。删除重复项使包大小减少了约 9%。
此问题通常不会发生,因为您拉取了同一库的两个不同版本,而是因为您和外部库之一依赖于同一库,但版本不同。这通常可以通过更新您所依赖的库来解决。
你的项目
考虑到所有这些,我们终于可以进入最后一块拼图 - 您的项目。您可以采取以下措施来缩小捆绑包并提高性能。
检查您的捆绑包
第一步是可见性。如果不了解捆绑包中的内容,减小捆绑包的大小就变成了一场猜谜游戏。为此,您可以使用我创建的名为 Sonda 的捆绑分析器和可视化工具。它适用于上述大多数捆绑程序(Parcel 除外),并准确显示参与捆绑的各个文件的大小。
您可以首先将其安装到您的项目中并目视检查捆绑包的各个部分。
一旦您充分了解了捆绑包内的内容并确定了可以优化的部分,您就可以单击图表图块来查看:
- 压缩前后的文件大小,
- 导入所选文件的文件列表,
- 甚至检查捆绑包中包含的部分源代码。
Sonda 还会警告您重复的依赖项,以便您可以快速识别并修复问题的根源。
理想情况下,您不仅应该进行一次性检查,还应该将持续监控设置为 CI 管道的一部分。跟踪一段时间内的变化,尤其是在大型项目中,可以帮助您防止小变化随着时间的推移滚雪球般变成严重的膨胀。
删除或优化外部库
最快的代码是您不发送的代码。只要有可能:
- 删除可以被原生 API 替换的库。
- 将重量级库替换为较小的替代品。
- 如果库支持,请使用优化的安装路径。
使用代码分割
如果您无法删除应用程序的某些部分,请尝试代码拆分。代码分割允许您推迟加载应用程序的某些部分,直到需要它们为止,从而缩短初始加载时间。
使用动态 import() 按需加载模块。例如,如果在用户单击按钮之前不需要某个特定功能,则推迟加载该功能直到那一刻。
现代前端框架支持开箱即用的延迟加载,使将代码分割集成到您的工作流程中比以往更容易。
遵循最佳实践
这是一般性建议,但值得重复。遵循最佳实践,例如:
- 使用最新的目标,这样代码就不会被不必要的转译或填充。一些polyfills可以添加很多现代浏览器中根本不需要的代码,但许多环境仍然默认添加它们。您还可以设置提醒,每年更新目标。
- 定期更新依赖项,因为新版本通常会更小或更快。这还可以防止您不得不处理安全漏洞或重复的依赖项。
- 评估您已经拥有或正在考虑添加的每个依赖项。如果您无法证明大小合理,请不要添加它或寻找更小的替代方案。
加入生态系统绩效 (e18e) 社区
如果您有兴趣让网络更快或只是学习新事物,您应该考虑加入生态系统性能社区。我们专注于三个主要领域:
- 清理 - 通过删除冗余依赖项或用现代替代方案替换它们来改进软件包。
- 加速 — 提高广泛使用的软件包的性能。
- 升级——构建过时软件包的现代替代品。
结论
我希望这篇文章说明您可以用更少的代码提供相同的功能。如果不加以管理,捆绑包大小可能会失控,但即使很小的更改也可以显着提高性能。
从今天开始:分析您的包、测试新工具或替换重量级库。其影响会让你大吃一惊。
我希望您喜欢这篇文章。如果您有任何问题或意见,或者如果您想了解有关特定主题的更多信息,请在下面的评论中告诉我。如果您想了解有关 JavaScript 性能、捆绑和 tree-shaking 主题的更多信息,您可以在此处关注我或在 BlueSky 上关注我并加入 e18e 社区。
以上是缩小 JavaScript 规模:掌握 Bundler 优化的详细内容。更多信息请关注PHP中文网其他相关文章!

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

禅工作室 13.0.1
功能强大的PHP集成开发环境

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

SublimeText3 Linux新版
SublimeText3 Linux最新版

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具