预提取的两种方法:<链接>标记和 HTTP 标头

德米安·伦祖利
Demián Renzulli

在此 Codelab 中,您将通过两种方式实现预提取:使用 <link rel="prefetch"> 和使用 HTTP Link 标头。

示例应用是一个网站,其促销着陆页为店内最畅销的 T 恤提供了特惠折扣。由于着陆页链接到单件商品,因此可以放心地假定大部分用户都会访问商品详情页面。因此,商品页面非常适合在着陆页上进行预提取。

衡量性能

首先确定基准性能:

  1. 点击 Remix to Edit 使项目可修改。
  2. 如需预览网站,请按查看应用,然后按全屏 全屏
  3. 按 `Control+Shift+J`(在 Mac 上,则按 `Command+Option+J`)打开开发者工具。
  4. 点击网络标签页。

  5. Throttling 下拉列表中,选择 Fast 3G,以模拟慢速连接类型。

  6. 如需加载商品页面,请点击示例应用中的立即购买

加载 product-details.html 页面大约需要 600 毫秒:

显示 product-details.html 加载时间的网络面板

为了改善导航效果,请在着陆页中插入 prefetch 标记以预提取 product-details.html 网页:

  • 将以下 <link> 元素添加到 views/index.html 文件的标头中:
<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">

      <link rel="prefetch" href="/product-details.html" as="document">
      ...
</head>

as 属性是可选的,但建议提供;该属性有助于浏览器设置正确的标头并确定资源是否已在缓存中。此属性的示例值包括:documentscriptstylefontimage其他

如需验证预提取是否正常运行,请执行以下操作:

  1. 如需预览网站,请按查看应用,然后按全屏 全屏
  2. 按 `Control+Shift+J`(在 Mac 上,则按 `Command+Option+J`)打开开发者工具。
  3. 点击网络标签页。

  4. Throttling 下拉列表中,选择 Fast 3G,以模拟慢速连接类型。

  5. 清除“停用缓存”复选框。

  6. 重新加载应用。

现在,当着陆页加载时,product-details.html 页面也会加载,但优先级最低:

显示已预提取的 product-details.html 文件的“Network”面板。

该网页会在 HTTP 缓存中保留 5 分钟,之后系统将应用文档的常规 Cache-Control 规则。在本例中,product-details.htmlcache-control 标头值为 public, max-age=0,这意味着网页总共会保留五分钟。

重新评估性能

  1. 重新加载应用。
  2. 如需加载商品页面,请点击示例应用中的立即购买

查看网络面板。与初始网络跟踪记录相比,有两个差异:

  • Size 列显示“预提取缓存”,这意味着该资源是从浏览器的缓存而不是从网络检索的。
  • 时间列显示现在加载文档大约需要 10 毫秒。

与上一版本(耗时约 600 毫秒)相比,此 API 减少了约 98%。

显示从预提取缓存中检索到的 product-details.html 的网络面板。

额外提示:使用“prefetch”进行渐进增强

最好将预提取作为渐进增强的方式实现,以供使用快速连接浏览的用户使用。您可以使用 Network Information API 检查网络状况,并据此动态注入预提取代码。如此一来,您可以最大限度地减少数据使用量,并为使用网速缓慢或昂贵的流量套餐的用户节省费用。

如需实现自适应预提取,请先从 views/index.html 中移除 <link rel="prefetch"> 标记:

<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
       <link rel="prefetch" href="/product-details.html" as="document">
       ...
    </head>

然后,将以下代码添加到 public/script.js,以声明一个在用户使用快速连接时动态注入 prefetch 标记的函数:

function injectLinkPrefetchIn4g(url) {
    if (window.navigator.connection.effectiveType === '4g') {
        //generate link prefetch tag
        const linkTag = document.createElement('link');
        linkTag.rel = 'prefetch';
        linkTag.href = url;
        linkTag.as = 'document';

        //inject tag in the head of the document
        document.head.appendChild(linkTag);
    }
}

此函数的工作方式如下:

  • 它会检查 Network Information APIeffectiveType 属性,以确定用户是否连接到了 4G(或更快)连接。
  • 如果满足该条件,它会生成一个 <link> 标记并以 prefetch 作为提示类型,传递将在 href 属性中预提取的网址,并在 as 属性中指明资源是 HTML document
  • 最后,它会在页面的 head 中动态注入脚本。

接下来,将 script.js 添加到 views/index.html 中,紧挨着结束 </body> 标记之前:

<body>
      ...
      <script src="/script.js"></script>
</body>

在网页末尾请求 script.js 可确保在解析和加载网页后加载和执行该代码段。

为确保预提取操作不会干扰当前网页的关键资源,请添加以下代码段以对 window.load 事件调用 injectLinkPrefetchIn4g()

<body>
      ...
      <script src="/script.js"></script>
      <script>
           window.addEventListener('load', () => {
                injectLinkPrefetchIn4g('/product-details.html');
           });
      </script>
</body>

着陆页现在仅在快速连接时预提取 product-details.html。为此,请执行以下操作:

  1. 如需预览网站,请按查看应用,然后按全屏 全屏
  2. 按 `Control+Shift+J`(在 Mac 上,则按 `Command+Option+J`)打开开发者工具。
  3. 点击网络标签页。
  4. Throttling 下拉列表中,选择 Online
  5. 重新加载应用。

您应该会在“网络”面板中看到 product-details.html

显示已预提取的 product-details.html 文件的“Network”面板。

如需验证在网速较慢时不会预提取商品页面,请执行以下操作:

  1. 在“Throttling”(节流)下拉列表中,选择 Slow 3G
  2. 重新加载应用。

Network 面板应仅包含不带 product-details.html 的着陆页的资源:

显示未预提取 product-details.html 的网络面板。

HTTP Link 标头可用于预提取与 link 标记相同类型的资源。决定何时使用其中一种格式主要取决于您的偏好,因为效果的差异微不足道。在这种情况下,您将使用它来预提取商品页面的主 CSS,以进一步改进其呈现效果。

在着陆页的服务器响应中为 style-product.css 添加 HTTP Link 标头:

  1. 打开 server.js 文件,然后查找根网址的 get() 处理程序:/
  2. 在处理程序的开头添加以下行:
app.get('/', function(request, response) {
    response.set('Link', '</style-product.css>; rel=prefetch');
    response.sendFile(__dirname + '/views/index.html');
});
  1. 如需预览网站,请按查看应用,然后按全屏 全屏
  2. 按 `Control+Shift+J`(在 Mac 上,则按 `Command+Option+J`)打开开发者工具。
  3. 点击网络标签页。
  4. 重新加载应用。

现在,着陆页加载后以最低优先级预提取 style-product.css

显示已预提取 style-product.css 的网络面板。

如需前往商品页面,请点击立即购买。查看 Network 面板:

显示从预提取缓存中检索到的 style-product.css 的网络面板。

从“预提取缓存”中检索了 style-product.css 文件,加载用时仅有 12 毫秒。