关于 HTTP/2 和打包的一些思考

Avatar of Jeremy Wagner
Jeremy Wagner

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费额度!

HTTP/2 一直是我关注的领域之一。 实际上,仅仅在去年我就写了几篇关于它的文章。 在其中一篇文章中,我做出了这个未经证实的断言

如果用户使用 HTTP/2: 您将提供更多更小的资源。 您将避免使用诸如图像雪碧图、内联 CSS 和脚本以及连接的样式表和脚本之类的东西。

我并不是唯一一个这样说的人,不过,公平地说,Rachel 在她的文章中用一些注意事项限定了她的断言。 公平地说,从理论上讲,这并非糟糕的建议。 HTTP/2 的多路复用功能使我们能够避免捆绑,而不会遭受头部阻塞的负面影响(我们在 HTTP/1 环境中对此非常熟悉)。 解开一些这些特定于 HTTP/1 的优化也可以使开发变得更容易。 在网络开发似乎比以往任何时候都更复杂的时候,谁不希望简单一些呢?

与任何在理论上看起来很简单的东西一样,将某些东西付诸实践可能是一件很麻烦的事情。 随着时间的推移,我收到了来自细心读者关于此主题的宝贵反馈,这让我重新思考了我关于哪些实践最适合 HTTP/2 环境的未经证实的断言。

反对打包的理由

关于为 HTTP/2 解包资源的争论主要围绕缓存展开。 前提是,如果您提供更多(更小)的资源而不是一个巨大的包,则对于具有已填充缓存的回头用户的缓存效率会更好。 讲得通。 如果一个小的资源发生更改并且该资源的缓存条目失效,则在下次访问时它将再次下载。 但是,如果只有包的一小部分发生更改,则必须重新下载整个巨大的包。 这并不是最佳选择。

为什么解包可能不是最佳选择

有时解开包是有意义的。 例如,代码分割 促进了更小、数量更多的资源,这些资源仅针对网站/应用程序的特定部分加载。 这是非常有意义的。 而不是预先加载网站的整个 JS 包,您可以将其分成更小的块并按需加载。 这可以保持各个页面的有效负载较低。 它还最大限度地减少了解析时间。 这是好事,因为过度的解析会导致页面绘制并变得可交互但尚未完全加载时出现卡顿和不愉快的体验。

但是,当我们将资源分割得太细时,有时会错过一个缺点:压缩率。 一般来说,较小的资源压缩效果不如较大的资源。 实际上,如果某些资源太小,则某些服务器配置将完全避免压缩它们,因为这样做没有实际收益。 让我们看看一些流行的 JavaScript 库的压缩效果如何

文件名 未压缩大小 Gzip(比率 %) Brotli(比率 %)
jquery-ui-1.12.1.min.js 247.72 KB 66.47 KB (26.83%) 55.8 KB (22.53%)
angular-1.6.4.min.js 163.21 KB 57.13 KB (35%) 49.99 KB (30.63%)
react-0.14.3.min.js 118.44 KB 30.62 KB (25.85%) 25.1 KB (21.19%)
jquery-3.2.1.min.js 84.63 KB 29.49 KB (34.85%) 26.63 KB (31.45%)
vue-2.3.3.min.js 77.16 KB 28.18 KB (36.52%)
zepto-1.2.0.min.js 25.77 KB 9.57 KB (37.14%)
preact-8.1.0.min.js 7.92 KB 3.31 KB (41.79%) 3.01 KB (38.01%)
rlite-2.0.1.min.js 1.07 KB 0.59 KB (55.14%) 0.5 KB (46.73%)

当然,这个比较表有点过头了,但它说明了一个关键点:作为经验法则,大型文件往往比小型文件产生更高的压缩率。 当您将大型包拆分为微小的块时,您将无法从压缩中获得那么多的好处。

当然,性能不仅仅是资源大小。 在 JavaScript 的情况下,我们可能希望倾向于更小的页面/模板特定文件,因为特定页面的初始加载在文件大小和解析时间方面都将更加流畅。 即使这些较小的资源本身压缩效果不佳。 就我个人而言,如果我正在构建一个应用程序,我会倾向于这样做。 在传统的、同步的“网站”式体验中,我不太倾向于追求代码分割。

然而,需要考虑的不仅仅是 JavaScript。 以 SVG 雪碧图为例。 在这些资源方面,打包似乎更有意义。 特别是对于大型雪碧图集。 我对一个 非常大的包含 223 个图标的图标集 进行了一个基本的测试。 在一个测试中,我提供了一个雪碧图版本的图标集。 在另一个测试中,我将每个图标作为单个资源提供。 在使用 SVG 雪碧图的测试中,图标集的总大小仅代表不到 10 KB 的压缩数据。 在使用解包资源的测试中,相同图标集的总大小为115 KB 的压缩数据。 即使有多路复用,在任何给定的连接上,115 KB 也不可能比 10 KB 加载得更快。 个别图标的压缩程度不足以弥补差异。技术旁注:在这两个测试中,SVG 图像都经过了 SVGO 优化。

旁注:一位敏锐的评论者 指出,Firefox 开发人员工具显示,在未使用雪碧图的测试中,传输了大约 38 KB 的数据。 这可能会影响您的优化方式。 只需要记住这一点。

不支持 HTTP/2 的浏览器

是的,这是个问题。 Opera Mini 特别是在这方面似乎是一个例外,并且根据您的用户,这可能不是一个可以忽略的用户群体。 虽然全球约 80% 的人使用可以支持 HTTP/2 的浏览器上网,但在世界的一些角落,这个数字有所下降。 例如,在印度,不到 50% 的用户使用可以与 HTTP/2 服务器通信的浏览器(无论如何,根据 caniuse 的说法)。 至少目前是这样的情况,并且支持趋势正在上升,但浏览器对该协议的普遍支持还有很长的路要走。

当用户使用不支持它的浏览器与 HTTP/2 服务器通信时会发生什么? 服务器将回退到 HTTP/1。 这意味着您将回到旧的性能优化范式。 所以再次,做好功课。 检查您的分析并查看您的用户来自哪里。 更好的是,利用 caniuse.com 的功能来分析您的分析并查看您的受众支持什么。

现实检验

是否有任何理智的开发者会将其前端代码设计为加载 223 个单独的 SVG 图像? 我希望不会,但是 没有什么能再让我感到惊讶了。 在除最复杂和功能最丰富的应用程序之外,您很难找到如此多的图标。 但是,对于您来说,将这些图标合并到雪碧图中并预先加载它以获得后续页面导航中更快渲染的好处可能更有意义。

这让我得出了一个不可避免的结论:在 Web 性能学科的各个角落,没有简单的答案,除了“做你的研究”。 依靠分析来决定打包是否对您的 HTTP/2 驱动网站有利。 您是否有许多只访问一两个页面然后离开的用户? 也许不要浪费时间打包东西。 您的用户是否在您的网站中深度导航并花费大量时间? 也许打包。

这一点对我来说很清楚:如果您将您的 HTTP/1 优化网站迁移到 HTTP/2 主机并且没有更改客户端架构中的任何内容,那将不会有什么大问题。 因此,不要相信一些编写博客文章的 Web 开发人员(例如,我)的笼统陈述。 弄清楚您的用户行为、什么优化最适合您的情况,并相应地调整您的代码。 祝你好运!


Cover of Web Performance in Action

Jeremy Wagner 是 Manning Publications 即将来临的图书 Web Performance in Action 的作者。 使用优惠券代码sswagner 可节省 42%。

在 Twitter 上关注他:@malchata