10

当从一个简单的登陆页面点击到一个重量级的单页应用程序时,我一直在尝试使用这样的东西来提高性能:

<link rel="prefetch" href="https://example.com" as="document" />
<link rel="prefetch" href="https://example.com/app.js" as="script" />
<link rel="prefetch" href="https://example.com/app.css" as="style" />

当我的登录页面位于子域上时,它似乎没有明显的性能提升。说,https://subdomain.example.com

当我单击链接访问时https://example.com,我仍然在 Chrome 网络选项卡中看到很长的延迟,因为app.jsapp.css已加载:

预取资源 预取资源下载时间

这是禁用预取的相同资源:

没有预取的资源下载时间

总共需要大致相同的时间。


使用预取缓存加载的资产之一的请求标头:

一般的:

Request URL: https://example.com/css/app.bffe365a.css
Request Method: GET
Status Code: 200  (from prefetch cache)
Remote Address: 13.226.219.19:443
Referrer Policy: no-referrer-when-downgrade

回复:

accept-ranges: bytes
cache-control: max-age=31536000
content-encoding: gzip
content-length: 39682
content-type: text/css
date: Mon, 06 Jan 2020 21:42:53 GMT
etag: "d6f5135674904979a2dfa9dab1d2c440"
last-modified: Mon, 06 Jan 2020 20:46:46 GMT
server: AmazonS3
status: 200
via: 1.1 example.cloudfront.net (CloudFront)
x-amz-cf-id: dO3yiCoPErExrE2BLYbUJaVye32FIJXXxMdI4neDGzGX9a6gcCDumg==
x-amz-cf-pop: LAX50-C1
x-amz-id-2: 1O0LmihxpHIywEaMQWX7G3FDAzxtH9tZq1T/jeVLMzifFSJSIIJSS6+175H61kKdAq6iEbwfs2I=
x-amz-request-id: AF35C178092B65D4
x-cache: Hit from cloudfront

要求:

DNT: 1
Referer: https://example.com/auth/join
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36

我的问题是:如果 Chrome 表明使用了预取缓存,那么为什么会有大量的内容下载时间?

Chrome 似乎有不同种类的缓存:预取缓存、磁盘缓存和内存缓存。磁盘缓存和内存缓存非常快(5ms 和 0ms 加载时间)。然而,有时 300 毫秒的下载时间,预取缓存毫无用处。我能从技术上解释为什么会发生这种情况吗?这是 Chrome 的错误吗?我在 Chrome 79.0.3945.117 上。

4

3 回答 3

0

添加<link rel=prefetch>到网页会告诉浏览器下载用户将来可能需要的整个页面或一些资源(如脚本或 CSS 文件)。这可以改善诸如 First Contentful Paint 和 Time to Interactive 之类的指标,并且通常可以使后续导航看起来立即加载。

在此处输入图像描述

对于不立即需要的资源,预取提示会消耗额外的字节,因此需要慎重应用此技术;仅在您确信用户需要资源时才预取资源。考虑在用户连接速度较慢时不要预取。您可以使用网络信息 API 检测到这一点。

有多种方法可以确定要预取哪些链接。最简单的一种是预取当前页面上的第一个链接或前几个链接。还有一些库使用更复杂的方法,本文稍后会解释 - https://web.dev/link-prefetch/

于 2020-01-03T11:08:35.713 回答
0

我只能猜测。自信的答案可能只有您自己通过实验才能找到。有太多变数需要考虑。但这里有一些想法:

  1. prefetch是浏览器的提示。浏览器可以出于某些任意原因忽略它。不仅如此,它的优先级最低。
  2. 例如,以防万一,请检查您的浏览器设置:(
    Menu/Settings/Advanced/Privacy and security/Preload pages for faster browsing and searching
    或类似的东西)。
  3. 如果您有任何机会使用移动互联网,这也可能是一个问题。
    https://www.technipages.com/google-chrome-prefetch
  4. 您从登录页面导航到 的速度有多快example.com
  5. 检查您的服务器日志以查看它是否曾经收到prefetch请求。
  6. 检查您的服务器是否设置了一些奇怪的标头以响应prefetch请求。例如Cache-Control: no-cache。是的,我看到你有cache-control: max-age=31536000,所以如果服务器会为同一个请求发送不同的标头(嗯......几乎相同,至少你没有说它们是,至少可以是一些标头表明它是一个prefetch请求),但奇怪的事情发生了。

  7. 您可能应该尝试添加crossorigin属性。例如

    <link rel="prefetch" href="https://example.com/app.css" as="style" crossorigin />

    在这里https://www.w3.org/TR/resource-hints/你可以找到这个例子

    <link rel="preconnect" href="//example.com">
    <link rel="preconnect" href="//cdn.example.com" crossorigin>
    

    与您的情况非常相关,但不幸的是没有解释。

  8. 在您的问题的原始版本中,您提到了服务人员...如果他们下载了某些东西,甚至您自己手动下载了某些东西,这也可能是问题所在。因为最低优先级prefetch

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Link_prefetching_FAQ#What_if_I.27m_downloading_something_in_the_background.3F_Will_link_prefetching_compete_for_bandwidth.3F

    如果您使用 Mozilla 下载内容,链接预取将延迟到任何后台下载完成

    我认为 Chrome 也是如此。

  9. 您是否尝试过将登录页面移至根域?如果是,并且prefetch按预期工作,那么是的 - 子域是问题的原因。GUI 消息Status Code: 200 (from prefetch cache)可能只是一个小故障。prefetch因为就在最近,Chrome 的行为开始发生一些变化。我还不知道事情是否解决了。基本上,是的,您有一定的概率prefetch只能来自同一来源。

    https://docs.google.com/document/d/1bKGDIePAuF6YXmmrwM33LeLvtuCsla3vTspsxsNp-f8/edit

于 2020-01-17T04:10:45.383 回答
-1

你应该添加下面的代码,以防你是子域并且你想要来自域的资源

<link rel="preconnect" href="https://example.com">
于 2020-01-18T08:34:32.767 回答