美文网首页前端三围
使用现代前端技术使旧版网站更具性能

使用现代前端技术使旧版网站更具性能

作者: 灵籁 | 来源:发表于2018-09-06 11:37 被阅读7次

译文:Making Legacy Sites More Performant with Modern Front-End Techniques by Mike Herchel MAY 26, 2018

今年早些时候,Lullabot致力于重新设计Pantheon的主页和几个登陆页面。如果你不熟悉Pantheon,他们就是Drupal和WordPress领域的领先托管公司之一。该项目的时间表非常雄心勃勃 - 需要在Drupalcon Nashville之前进行推广。作为Drupal社区的长期合作伙伴,我们很高兴接受这一点。

前端开发团队加入,而我们的设计团队仍在努力工作。我们的任务是:1)熟悉当前的Drupal 7代码库;2)尽可能地改进性能。所有这一切都伴随着警告,当设计降落时,我们应该立即继续前进。 跳进Pantheon的代码库很有意思。这是我们已经看过几百次的情况:代码库以模块化方式开始,但随着时间的推移和多个开发人员的工作,代码库变得更大,更慢,更笨拙。这个问题并不是Drupal特有的 - 它是许多技术的常见流行病。

定义网站速度

网站速度是后端速度和浏览器渲染速度的组合,由前端代码决定。Pantheon的后端速度令人印象深刻。除了在Pantheon的基础设施上构建之外,他们还将Fastly CDN与HTTP / 2集成在一起

最终用户响应时间的80-90%用于前端。从那里开始。 - 史蒂夫索德斯

在正常情况下,前端占浏览器呈现网站所需时间的80%。在我们的情况下,它更像是90%。
这意味着我们可以进行大量优化以使网站更快。精彩!

确定我们将使用的指标

对于本文,我们将集中讨论四个主要的网站速度指标:

  • Time to First Byte - 这是服务器获取HTML的第一个字节所需的时间。在我们的案例中,Pantheon的基础设施处理得非常好。
  • Time to First Paint - 这是浏览器最初完成DOM的布局并开始绘制屏幕的时间。
  • Time to Last Hero Paint - 这是浏览器在初始视口中完成绘制英雄所需的时间。
  • Time to First Interactive - 这是最重要的指标。这是当网站被绘制并变得可用时(按钮可点击,JavaScript工作等)。

我们将在本文中介绍Chrome开发者工具的性能面板(performance)。此配置文件是在网站的预设计版本上进行的,并标识了这些指标。

perf-panel-before-redesign-annotated.jpg

H2的前端性能

HTTP / 2(又名H2)是Web上的一种新技术,它管理服务器如何在浏览器之间来回传输数据。使用先前版本的HTTP(1.1),每个资源请求都需要整个TCP握手,这会导致每个请求产生额外的延迟。为了缓解这种情况,前端开发人员会将资源聚合到尽可能少的文件中。例如,前端开发人员会将多个CSS文件合并为一个整体文件。我们还将多个小图像组合成一个“精灵”图像(即雪碧图),并且一次只显示部分图像。这些“黑客”减少了HTTP请求的数量。 使用H2,协议本身可以在很大程度上减轻这些问题,让前端开发人员将资源分配到自己的逻辑文件中。 H2允许在一个TCP流下多路复用多个文件。由于Pantheon已将H2与其全球CDN集成,因此我们能够利用这些新的优化。

确定问题

前端没有优化。我们来看看Chrome开发者工具中的network:

network-tab-prior-optimizations-all.jpg

首先要注意的是聚合的CSS包是1.4MB解压缩。这对于CSS文件来说非常大,值得进一步调查。

第二件事要注意:网站正在加载一些可能在主页上没有使用的JavaScript文件。

perf-tab-prior-optimizations.jpg

让我们首先优化CSS包

一个1.4MB的CSS捆绑包很麻烦,会伤害我们的Time to First Paint指标,以及之后发生的所有指标。除了必须下载更大的文件外,浏览器还必须解析和解释它。

深入研究这个CSS包,我们发现了一些嵌入式base64和编码的SVG图像。使用HTTP / 1.1时,这会将往返请求保存到服务器以获取该资源,但这意味着浏览器会下载图像,无论该页面是否需要它。此外,我们发现许多这些图像属于不再使用的组件。

类似地,各种登陆页面仅使用单片CSS文件的一小部分。为了减少CSS包大小,我们最初采取双管齐下的方法:

  • 提取嵌入的图像,并通过标准的CSS background-image属性引用它们。因为Pantheon带有集成的HTTP / 2,所以将它们作为单独的文件加载几乎没有性能损失。
  • 将单片CSS文件拆分为多个文件,并根据需要加载这些较小的文件,类似于现代“代码拆分”工具所采用的方法。

删除嵌入的图像将捆绑包删减到大约700KB - 这是一个很大的改进,但仍然是一个非常大的CSS文件。下一步是将CSS包“代码拆分”成多个文件。 Pantheon的代码库使用了各种可能使这个相对简单的Sass部分。不幸的是,Sass代码库有很大的部分内容和有限的代码文档。

编写可维护的Sass很难。 CSS本质上将DOM级别“级联”到各种组件中。接下来也不可能知道HTML代码库中确切存在特定CSS选择器的位置。 Pantheon的Sass代码库是这些常见问题的完美例子。在移动代码时,我们无法预料到所有潜在的视觉修改。

编写易于维护的SASS

编写易于维护的Sass很难,但这并非不可能。要有效地执行此操作,您需要使代码易于删除。您可以通过以下方法完成此任务:

  • 保持你的Sass部分小而模块化。当它们达到300多行时,开始考虑将它们分开。
  • 关于每个组件的详细注释,详细说明它是什么,它看起来是什么,以及何时使用它。
  • 使用像BEM这样的命名约定并坚持下去。
  • 内联注释详细说明任何不标准的内容,例如!重要声明,幻数,黑客等。

改造SASS 代码库

重构纠结的Sass代码库需要一些试验和错误,但如果没有内置于持续集成(CI)系统的可视化回归系统,这是不可能的。

幸运的是,Pantheon将BackstopJS集成在他们的CI管道中。该系统查看多个视口宽度的代表性URL列表。提交拉取请求时,它会使用无头Chrome浏览器到达参考站点,并将其与包含拉取请求中的代码的Pantheon Multidev环境进行比较。如果它检测到差异,它将标记此并显示粉红色的差异。

backstopjs_report.jpg

通过努力,我们能够将Sass代码库重构为13个独立的文件。然后在Drupal中,我们编写了一个自定义预处理函数,它只为每种内容类型加载CSS。

从这一点来看,我们能够将主要的CSS文件降低到可管理的400KB(通过线路只有70KB)。虽然仍然庞大,但它在技术上已经不再那么多了。仍然可以进行一些优化,但通过这些方法,我们将此文件的大小减小到原始大小的三分之一。

优化JavaScript堆栈

Pantheon的主题创建于2015年,并大量使用jQuery,这在当时是一种常见的做法。虽然我们没有时间或预算将jQuery重构出网站,但我们确实有时间进行一些简单而重要的优化。

与同等大小的图像或媒体文件相比,JavaScript文件在浏览器上需要花费更多精力。每个JavaScript文件都必须在运行中进行编译然后执行,这会占用主线程并延迟Time to Interactive指标。这会导致浏览器无响应并锁定,并且在移动电话等低功耗设备上非常常见。

此外,标题中包含的JavaScript文件也会阻止布局的渲染,这会延迟“首次绘制时间”度量标准。

perf-tab-prior-opt-main-threa-annotated.jpg

避免延迟这些指标的最简单方法很简单:删除不需要的JavaScript。为此,我们列出了当前正在使用的库,并列出了实例化各种方法的选择器。接下来,我们使用Wget抓取网站的整个HTML,并交叉引用这些选择器的已删除HTML。

# Recursively scrape the site, ignore specific extensions, and append .html extension.
wget http://panther.local -r -R gif,jpg,pdf,css,js,svg,png –adjust-extension

一旦我们列出了我们需要每个库的位置和时间,我们修改了Drupal的预处理层,以便仅在必要时加载它们。通过这个,我们将JavaScript包大小减少了几百kb!此外,我们尽可能多地将JavaScript文件移动到页脚中(从而改善了第一次绘制的时间)。

额外的前端性能获胜

在推出新设计之后,我们从性能角度对网站进行了额外的审视。

perf-tab-showing-font-relayout.jpg

您可以在上图中看到在渲染过程的后期发生了额外的布局操作。如果我们仔细观察,Chrome开发者工具可让我们对此进行跟踪。

这种后期布局操作的原因是一系列因素:首先,我们使用font-display:swap;声明。此声明告诉浏览器首先使用系统字体呈现页面,然后在下载Web字体时重新呈现。这是一种很好的做法,因为它可以显着减少慢速连接上的“首次绘制时间”度量标准。

这里,这种后期布局操作的主要原因是网络字体下载较晚。浏览器必须首先下载并解析CSS包,然后将其与DOM进行协调,以便开始下载Web字体。这吃了重要的微秒。

fonts-downloading-late.jpg

在上图中,请注意在高优先级Web字体之前下载的低优先级图像。在这种情况下,要下载的第一个Web字体是第52个要下载的资源!

通过资源提示预加载web字体

我们真正需要做的是先加载我们的web字体。幸运的是,我们可以使用资源提示预加载我们的Web字体!

<link rel="preload" href="/sites/all/themes/zeus/fonts/tablet_gothic/360074_3_0.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/sites/all/themes/zeus/fonts/tablet_gothic/360074_2_0.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/sites/all/themes/zeus/fonts/tablet_gothic/360074_4_0.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/sites/all/themes/zeus/fonts/tablet_gothic/360074_1_0.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/sites/all/themes/zeus/fonts/tablet_gothic_condensed/360074_5_0.woff2" as="font" type="font/woff2" crossorigin>
fonts-downloading-early.jpg

是通过资源提示,浏览器立即了解文件并尽快下载文件。这消除了无格式内容(FOUT)的重新布局和相关闪存。它还缩短了Time to Last Hero Paint指标的时间。

perf-tab-after-font-optimizations.jpg

通过资源提示预加载响应式图像

我们来看看Chrome开发者工具的network标签中的电影地带视图。为此,请单击看起来像相机的工具栏图标。当我们刷新时,我们可以看到一切都在快速加载 - 除了Hero的背景图像。这会影响Last Hero Paint指标。

background-image-loading-late.jpg

如果我们跳转到“network”选项卡,我们会看到英雄图像是要下载的第65个资源。这是因为图像是通过CSS background-image属性引用的。要下载图像,浏览器必须首先下载并解释CSS包,然后与DOM交叉引用它。

我们需要找到一种方法来为这个图像做资源提示。但是,为了节省带宽,我们根据屏幕宽度加载不同版本的背景图像。为了确保我们下载正确的图像,我们在link元素上包含了media属性。

我们需要确保我们不加载同一背景图像的多个版本,我们当然不想获取不需要的资源。

<link rel="preload" href="/<?php print $zeus_theme_path; ?>/images/new-design/homepage/hero-image-primary--small.jpg" as="image" media="(max-width: 640px)">
  <link rel="preload" href="/<?php print $zeus_theme_path; ?>/images/new-design/homepage/hero-image-primary--med.jpg" as="image" media="(min-width: 640px) and (max-width: 980px)">
  <link rel="preload" href="/<?php print $zeus_theme_path; ?>/images/new-design/homepage/hero-image-primary--med-large.jpg" as="image" media="(min-width: 980px) and (max-width: 1200px)">
  <link rel="preload" href="/<?php print $zeus_theme_path; ?>/images/new-design/homepage/hero-image-primary.jpg" as="image" media="(min-width: 1200px)">

此时,视口的正确背景图像将在字体后立即下载,这将完全删除FOUT(无样式内容的闪烁) - 至少在快速连接上。

结论

前端网站性能是一个不断变化的目标,但对于网站的整体速度至关重要。最佳实践不断发展。此外,现代浏览器不断更新识别问题和优化渲染所需的性能技术和工具。这些优化不一定非常困难,通常可以在几个小时内完成。

before-after.jpg

特别感谢

特别感谢我在这个项目上的kickass同事:Marc Drummond,Jerad Bitner,Nate Lampton和Helena McCabe。还有Lullabot的设计师Maggie Griner,Marissa Epstein和Jared Ponchot。 还要特别感谢我们在Pantheon的惊人同行:Matt Stodolnic,Sarah Fruy,Michelle Buggy,Nikita Tselovalnikov和Steve Persch。

相关文章

网友评论

    本文标题:使用现代前端技术使旧版网站更具性能

    本文链接:https://www.haomeiwen.com/subject/ehitgftx.html