在
<link>
中添加rel=preconnect
会通知浏览器您的页面打算与另一个域名建立连接,并且您希望该过程尽快开始。因为设置过程在浏览器请求资源之前就已经完成,所以资源将加载得更快。
文章中的图形很好地说明了为什么将其作为提高性能的明显选择。

几年前,Robin 对所有这类内容进行了 很好的总结。看起来现在最佳实践是使用这两个方法。
<link rel="preconnect" href="http://example.com">
<link rel="dns-prefetch" href="http://example.com">
对于您加载文档的主域名之外的所有域名。
快速查看一下 CSS-Tricks 资源,我得到
secure.gravatar.com
static.codepen.io
res.cloudinary.com
ad.doubleclick.com
s3.buysellads.com
srv.buysellads.com
www.google-analytics.com
这将在每个请求的网站上,在数据包的前几个数据包中额外添加 14 个 <link>
标签。这听起来像是性能的提升,但我想在不假思索地将其添加进去之前进行测试。
那么预连接能产生什么区别呢?
我使用 HTTP Archive 查找了几个使用 Cloudinary 作为其图像的网站,并对其进行了未修改的测试,然后又注入了预连接脚本进行了测试。每个测试都进行了九次运行,使用 Chrome 模拟移动设备以及 Cable 网络配置文件。
在 第一个网站 上,视觉效果有了明显的改善,主要背景图像的加载速度比未修改的网站(底部)提前了半秒以上(顶部)。

这些东西让我想起了 instant.page(刚刚发布了 v2 版本),这是一个花哨的小脚本,可以根据交互预加载内容。它现在是一个浏览器扩展程序(FasterChrome),我一直在试用。我不能说我注意到很大的区别,但我几乎总是使用快速的互联网连接。
这与缓存如何配合使用?如果我是页面的回头客,并且所有 CDN 图像都被缓存,则浏览器根本不需要连接到该域名。在这种情况下,预连接是否会增加不必要的开销?
正确,第一次非缓存访问将受益于预连接,但对相同资源的重复请求可能已经被缓存,然后将从缓存中提供服务,从而使预连接变得不必要。
但是,预连接仍然更好,因为
(1) 对于第一次非缓存的资源请求,您仍然可以从预连接中受益。
(2) Googlebot 不会缓存资源,因此每个资源请求都是第一次,因此 Google 测量的页面速度将受益。
(3) 预连接不会阻止渲染,异步发生,不会影响 DOM,因此不会影响页面速度、交互时间、首次绘制时间等。它完全独立且并行发生,因此页面速度不会受到影响。
(4) 是的,每个预连接都会在浏览器上使用极少量的资源,但只有当您调用大量预连接时,才会导致浏览器负担过重。
(5) 如果用户访问第一个页面,则执行预连接并建立与资源(例如 CDN)的连接。如果用户然后单击链接转到另一个页面(在保持活动时间内),该页面也从 CDN 中提取内容,则浏览器会看到该第二个页面上的预连接请求,但也看到它由于 HTTP 连接的 TCP 保持活动功能而已经打开了该连接。因此,它显然不会尝试连接到已打开的连接。
大约一年前,我在一个正在开发的网站中添加了资源提示。它预连接到其他域名(主要是 Google),并预取 JavaScript。我认为它每个页面节省了 200 毫秒,如果通过 HTTPS 连接并且 TLS 握手速度较慢,则可能会更大(我们的大多数握手速度都很快)。
我认为 dns-prefetch 应该是多余的;预连接会强制浏览器解析 DNS 地址。
如果浏览器支持预连接,则 dns-prefetch 没有必要,因为使用预连接建立与主机的连接也会执行 DNS 查找。但是,一些旧版浏览器不支持预连接,因此 dns-prefetch 行是针对这些浏览器的后备方案。这样,浏览器至少可以在请求资源之前执行 DNS 查找。
有趣。在这些情况下,子域有多重要?
示例
这会打开与 Google Fonts 的整个连接(DNS/TLS/…)。这可能很有用,因为字体通常由您网站上的所有页面使用。
<link rel="preconnect" href="https://fonts.gstatic.com">
但是 Google API 的 uri 呢?通常由 Google 地图或其他服务使用,这些服务并不总是在所有页面上加载,因此 dns-fetch 可能是更好的选择?
<link rel="dns-fetch" href="https://googleapis.com">
上面的代码是否可以完美运行,或者我们是否真的应该这样做
<link rel="dns-fetch" href="https://maps.googleapis.com">
<link rel="dns-fetch" href="https://ajax.googleapis.ac.cn">
<link rel="dns-fetch" href="https://service.googleapis.com">
我认为您需要在其中明确指定子域名。有人知道确切情况吗?
由于正在与目标 Web 服务器建立实际的 HTTP/TLS 连接,并且 maps.googleapis.com 肯定与 ajax.googleapis.com 是不同的 Web 服务器,因此需要子域名/主机。因此,不包含子域名会导致您与错误的服务器建立连接,从而使预连接毫无用处。
关于 Google 字体,预连接到样式表主机 fonts.googleapis.com 以获取样式表几乎没有任何好处,因为这将在 HTML 解析的早期阶段被提取。但是,该样式表随后会从 fonts.gstatic.com 请求实际的字体文件,因此为了预期而预连接到 fonts.gstatic.com 有助于提高性能。
仅当作为不支持预连接的浏览器的后备方案时,使用 dns-prefetch 才有意义。如果您只针对支持预连接的浏览器,则 dns-prefetch 没有价值。
如果提到的链接是当前网站(我的意思是内部绝对链接),而不是外部链接,会怎么样?
我认为困难的部分在于说服决策者它值得这样做。就像您在最后一句话中所说的那样,我几乎总是使用快速的互联网连接。
您好,Chris
感谢这篇文章。我看到在 css-tricks.com 上,您选择不为 google-analytics.com 使用预连接或 dns-prefetch。背后的原因是什么?我目前正在考虑专门为 Google Analytics 和 Facebook 使用这些资源提示。
preconnect
应该用于将在网站上进一步导航时加载的资源。因此,在我看来,由于 Google Analytics 应该在每个页面上都可用,它是在第一页加载时加载的,因此无需预加载它。