在此 Codelab 中,您将通过两种方式实现预提取:使用 <link rel="prefetch">
和使用 HTTP Link
标头。
此示例应用是一个网站,其中包含一个宣传着陆页,其中显示了商店最畅销 T 恤的特别折扣。由于着陆页链接到单个商品,因此可以放心地假设,很大一部分用户会前往商品详情页面。因此,商品页面非常适合在着陆页上进行预提取。
衡量效果
首先,确定基准性能:
- 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
点击网络标签页。
在节流下拉列表中,选择快速 3G 以模拟慢速连接类型。
如需加载商品页面,请在示例应用中点击立即购买。
product-details.html
页面的加载时间约为 600 毫秒:
使用 <link rel="prefetch">
预提取商品页面
为了改进导航,请在着陆页中插入 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
属性是可选的,但建议使用;它有助于浏览器设置正确的标头,并确定资源是否已在缓存中。此属性的示例值包括:document
、script
、style
、font
、image
和其他。
如需验证预提取是否正常运行,请执行以下操作:
- 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
点击网络标签页。
在节流下拉列表中,选择快速 3G 以模拟慢速连接类型。
清除“禁用缓存”复选框。
重新加载应用。
现在,当着陆页加载时,product-details.html
也会加载,但优先级最低:
该网页会在 HTTP 缓存中保留 5 分钟,之后该文档会应用正常的 Cache-Control
规则。在这种情况下,product-details.html
具有值为 public, max-age=0
的 cache-control
标头,这意味着网页总共保留五分钟。
重新评估效果
- 重新加载应用。
- 如需加载商品页面,请在示例应用中点击立即购买。
查看网络面板。与初始网络轨迹相比,有以下两点不同:
- “Size”(大小)列显示“prefetch cache”(预提取缓存),这意味着相应资源是从浏览器的缓存(而非网络)中检索的。
- 时间列显示,文档加载所需的时间现在约为 10 毫秒。
与之前的版本(大约需要 600 毫秒)相比,这大约减少了 98%。
加分题:使用 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 API 的 effectiveType 属性,以确定用户是否使用的是 4G(或更快的)连接。
- 如果满足该条件,它会生成一个
<link>
标记,其中prefetch
是提示类型,href
属性中传递的是将要预提取的网址,as
属性中指示的是资源为 HTMLdocument
。 - 最后,它会在网页的
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
。验证:
- 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
- 点击网络标签页。
- 在节流下拉列表中,选择在线。
- 重新加载应用。
您应该会在“网络”面板中看到 product-details.html
:
如需验证商品页面是否未在慢速连接上预提取,请执行以下操作:
- 在“节流”下拉列表中,选择 Slow 3G。
- 重新加载应用。
网络面板应仅包含不含 product-details.html
的着陆页资源:
使用 HTTP Link
标头预提取商品页面的样式表
HTTP Link
标头可用于预提取与 link
标记相同类型的资源。决定何时使用其中一种方法主要取决于您的偏好,因为性能差异微不足道。在这种情况下,您将使用它来预提取商品页面的主要 CSS,以进一步改进其渲染。
在着陆页的服务器响应中,为 style-product.css
添加 HTTP Link
标头:
- 打开
server.js
文件,然后查找根网址的get()
处理程序:/
。 - 在处理脚本的开头添加以下代码行:
app.get('/', function(request, response) {
response.set('Link', '</style-product.css>; rel=prefetch');
response.sendFile(__dirname + '/views/index.html');
});
- 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
- 点击网络标签页。
- 重新加载应用。
现在,在着陆页加载后,系统会以最低优先级预提取 style-product.css
:
如需前往商品页面,请点击立即购买。查看网络面板:
系统从“预提取缓存”中检索了 style-product.css
文件,加载该文件仅用了 12 毫秒。