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

Demián Renzulli
Demián Renzulli

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

此示例应用是一个网站,其中包含一个宣传着陆页,其中显示了商店最畅销 T 恤的特别折扣。由于着陆页链接到单个商品,因此可以放心地假设,很大一部分用户会前往商品详情页面。因此,商品页面非常适合在着陆页上进行预提取。

衡量效果

首先,确定基准性能:

  1. 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
  2. 点击网络标签页。

  3. 节流下拉列表中,选择快速 3G 以模拟慢速连接类型。

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

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. 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
  2. 点击网络标签页。

  3. 节流下拉列表中,选择快速 3G 以模拟慢速连接类型。

  4. 清除“禁用缓存”复选框。

  5. 重新加载应用。

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

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

该网页会在 HTTP 缓存中保留 5 分钟,之后该文档会应用正常的 Cache-Control 规则。在这种情况下,product-details.html 具有值为 public, max-age=0cache-control 标头,这意味着网页总共保留五分钟。

重新评估效果

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

查看网络面板。与初始网络轨迹相比,有以下两点不同:

  • “Size”(大小)列显示“prefetch cache”(预提取缓存),这意味着相应资源是从浏览器的缓存(而非网络)中检索的。
  • 时间列显示,文档加载所需的时间现在约为 10 毫秒。

与之前的版本(大约需要 600 毫秒)相比,这大约减少了 98%。

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

加分题:使用 prefetch 作为渐进增强功能

预提取最好作为一种渐进式增强功能来实现,以供使用快速连接浏览的用户使用。您可以使用网络信息 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. 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
  2. 点击网络标签页。
  3. 节流下拉列表中,选择在线
  4. 重新加载应用。

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

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

如需验证商品页面是否未在慢速连接上预提取,请执行以下操作:

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

网络面板应仅包含不含 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. 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
  2. 点击网络标签页。
  3. 重新加载应用。

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

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

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

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

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