Proload、Preconnect、Prefetch:使用资源提示提高网站性能Proload、Preconnect、P
[引导]
资源提示(Resource Hint)是 HTML 中的标签,有助于浏览器更快地加载网页。
同时资源提示也是一种使用
<link>
或<script>
等标签来提示浏览器有关资源的方式使用它们,您可以加快页面加载速度并提供更好的用户体验——预加载获取并缓存关键资源,预连接建立到外部站点的早期连接,预取预加载可能需要的资源。
资源提示的用处
现代 Web 浏览器使用各种不同的技术来提高网站的整体性能:
例如:从优先考虑最重要的资源并首先获取它们,到猜测用户将访问的下一个页面。
但是作为开发者你不能只依赖于浏览器,而是要了解哪些资源最重要,要从哪些方面提高网站的整体性能、感知速度和用户体验。往往资源提示可以帮助我们让浏览器更快的加载你开发的页面。
同时我们需要只知道他们的最优使用方式。
浏览器如何工作
为了更好地理解资源提示及其适用范围,我们需要简单的知道浏览器是如何工作的,这显示是非常重要!
[!提示]
以下几行是对浏览器工作方式的过度简化。如果你想更深入地了解这个过程,你应该查看这篇文章 - 填充页面:浏览器是如何工作的。
可以将浏览器加载页面简化为三个过程:
- 建立联系
- 下载、解析和渲染
- 使页面具有交互性
第一阶段:浏览器需要与服务器建立连接才能下载资源。其中查找域名并将其解析为IP地址、设置与服务器的连接以及加密连接以确保安全。
第二阶段:完成上述操作后,浏览器可以继续下载和解析,构建文档对象模型 (DOM) 和 CSS 对象模型 (CSSOM),然后呈现内容。
第三阶段:使页面具有交互性。上面提到的所有进程都发生在主线程中。因此,在浏览器的主线程完成解析、渲染和绘制页面后,是时候处理延迟的 JavaScript 文件了,使页面可用于滚动、触摸等其他交互性。
上述就是浏览器加载页面的幕后的过程(过度简化的过程,浏览器实现这些是及其复杂的)
下面就是我们怎么通过资源提示,让其再每个阶段发挥积极的作用。
资源提示:profetch、proconnect、proload
顾名思义,资源提示是告诉浏览器应该如何处理特定资源或网页的提示或说明。换句话说,这组指令允许您帮助浏览器确定需要获取和呈现的源或资源的优先级。
所有资源提示都使用 link 元素的 rel 属性,该元素位于 HTML 文档的头部。
将这些 HTML 代码片段集成到您的网站上将允许浏览器比浏览器通过正常加载页面过程找到它们更早地开始加载所选文件。
通俗点就是:通过手动指定让浏览器按照你设定的优先级加载资源。
下面就是进入主题了
prefetch (预取)
prefetch 是一个低优先级的资源提示,它允许浏览器获取以后可能需要的资源并将它们存储在浏览器的缓存中。
示意图:
代码示例:
<link rel="prefetch" href="next.html" />
强调一下:
[注意]
由于 prefetch 设置的优先级非常低,因此不要对重要性较高的文件使用此提示。
正确的示例:
利用预取来缩短后续页面的加载时间
例如,您可以在用户身份验证期间应用 prefetch 指令。这样,您可以利用他们输入凭据所需的时间来预加载他们接下来将看到的页面所需的资源。
通过预测访问者在您网站上的步骤并预取资源,您可以改进FCP( First Contentful Paint )和 Time to Interactive 等指标。(Netflix 就是非常好的示例,并将他们的互动时间缩短了 30%)
到目前为止,我们提到的一切都与预取有关,也称为链接预取。但是还有另外两种类型的预取同样重要,我们不得不提到:
dns-prefetch (dns预取)
在连接到主机(源服务器)之前,浏览器需要执行 DNS 查找以将主机名(URL)转换为 IP 地址。
虽然这通常只需要几毫秒,但如果网站从第三方域名加载文件,而大多数网站都会这样做,浏览器必须为每个域执行 DNS 查找。一些网站(例如,新闻网站)使用大量外部资源,这意味着每个页面可能需要数十次 DNS 查找。
在这些情况下,使用 dns-prefetch 提示可能会节省几毫秒,因为指令会告诉浏览器立即启动该进程,而不是在加载过程的后期发现需求。
正如 Web Almanac 2021 年版年鉴中所建议的,一个好的做法是将 dns-prefetch 与 preconnect 提示相结合以获得最佳结果。您可以在我们讨论 preconnect 的部分了解原因。
prerender (预渲染)
prerender (预渲染)与预取非常相似,因为它优化了用户接下来可能导航到的资源。区别在于 prerender 实际上渲染的是整个页面,而不是特定的资源。
代码示例:
<link rel="prerender" href="blog.html" />
preconnect (预连接)
与 dns-prefetch 一样,preconnect 指令帮助浏览器在向服务器发送初始请求之前建立早期连接。
但是,preconnect 提示更进一步。虽然它执行 DNS 查找,但它还包括 TLS 协商和 TCP 握手。这反过来又消除了往返延迟并节省了更多时间。
示意图:
灵魂拷问:preconnect可以完成 dns-prefetch 的所有操作,甚至更高,为什么我们为啥不直接使用preconnect?
答案:兼容性,某些浏览器的版本并不支持preconnect。
示意图:
聪明的你是不是想到了解决方案,对的,就是这么干:
// 一起使用它们以充分利用它们:
// 您可以在支持 preconnect 的浏览器中从 preconnect 中受益,不支持的话回退到 dns-prefetch
<link rel="preconnect" href="https://example.com" />
<link rel="dns-prefetch" href="https://example.com" />
下面是Google的一段描述:
“You can speed up the load time by 100–500 ms by establishing early connections to important third-party origins. These numbers might seem small, but they make a difference in how users perceive web page performance.”
翻译一下就是:
“您可以通过建立与重要的第三方源站的早期连接,将加载时间加快 100-500 毫秒。这些数字可能看起来很小,但它们会对用户如何看待网页性能产生影响。
preload (预加载)
在了解 preload 指令的工作原理之前,我们必须弄清楚一些事情!
尽管 preload 经常被称为 “Resource Hint”,但事实并非如此。preload 是一种声明式的 fetch,对于浏览器来说是必需的,这使得它更像是一个命令而不是一个提示。
预加载用于强制浏览器在浏览器发现资源之前下载资源,因为它对页面至关重要。
preload 指令在属于关键渲染路径但不易被浏览器发现的资源上效果最佳。
例如,字体、CSS 或关键的 JavaScript。
注意:
与 dns-prefetch 和 preconnect 提示的另一个区别是,虽然它们只需要 rel 和 href 属性,但 preload 更复杂。您必须添加 as 属性,该属性指示要预加载的资源内容类型。
代码示例:
<link rel="preload" as="image” href="header-logo.svg" />
下面是Google的一段描述:
“If you don’t supply a valid “as” when specifying what to preload, for example, scripts, you will end up fetching twice.”
翻译一下就是:
“如果你在指定要预加载的内容(例如脚本)时没有提供有效的 'as',你最终会获取两次。”
以下是您可以指定的 as 值的完整列表:
强调:包含 as 属性有助于浏览器根据预取资源的类型设置预取资源的优先级,并确定该资源是否已经存在于缓存中。
同时:对于某些资源(如字体),您还必须包含 crossorigin 属性。
crossorigin 属性将请求的模式设置为 HTTP CORS 请求。CORS(跨域资源共享)是一种机制,它允许服务器指示浏览器应允许加载资源的任何源,而不是自己的源。我们不会对此进行深入研究,因为它不是本文的重点,但您可以在此处找到更多信息。
并且类似于 as 属性,预加载没有 crossorigin 的字体会重复获取
使用资源提示会带来哪些问题
-
prefecth可能会增加数据消耗
-
prerender会导致带宽浪费
-
proconnect可能会导致额外的 CPU 使用率
-
proload可能会覆盖浏览器分析器设置的优先级
扩展
上面一直再说Pre的操作,既然有预操作,那自然而然的就会有延迟操作。那么有两个标签就需要我们了解,async和defer。
async
async表示异步操作。
详细解释:
当浏览器遇到带有 async 属性的 script 时,请求该脚本的网络请求是异步的,不会阻塞浏览器解析 HTML,一旦网络请求回来之后,如果此时 HTML 还没有解析完,浏览器会暂停解析,先让 JS 引擎执行代码,执行完毕后再进行解析。
上面这句话,记住,记不住的话可以借助下面的示意图加强理解。
代码示例:
<script src="http://xxxx.com/xxx.js" async></script>
示意图:
还有一直比较理想的情况,就是 JS 脚本请求回来之前,HTML 已经解析完毕,那就会立即执行请求完的js。
示意图:
defer
defer表示延迟操作。
详细解释:
当浏览器遇到带有 defer 属性的 script 时,获取该脚本的网络请求也是异步的,不会阻塞浏览器解析 HTML,一旦网络请求回来之后,如果此时 HTML 还没有解析完,浏览器不会暂停解析并执行 js 代码,而是等待 HTML 解析完毕再执行 js 代码。
上面这句话,记住,记不住的话可以借助下面的示意图加强理解。
代码示例:
<script src="http://xxxx.com/xxx.js" defer></script>
示意图:
总结
其实,async和defer最大的区别点就是,是否会阻止继续渲染,阻止的就是async,不阻止的就是defer,这可以很容易的帮助我们区分两者。
script标签 | JS执行顺序 | 是否阻塞HTML解析 |
---|---|---|
script | 再HTML中的顺序 | 阻塞 |
script async | 网络请求返回的顺序 | 可能阻塞,也可能不阻塞 |
script defer | 再HTML中的顺序 | 不阻塞 |
参考地址:
转载自:https://juejin.cn/post/7411406818026717194