1. 资源加载优先级
在浏览器发起网络请求时,并非每个字节都具有相同的优先级,所以,浏览器通常会对所要加载的内容进行推测,将相对重要的信息先呈现给用户。比如浏览器一般会先加载CSS,再去加载JavaScript脚本和图像文件。当然,浏览器的判断并不一定都是准确的,下面就来看看如何影响浏览器对资源加载的优先级。
浏览器是基于自身的启发式算法,会对资源的重要性进行判断,来划分优先级,通常从低到高分为Lowest、Low、High、Highest等。比如在head标签中,CSS文件通常具有最高的优先级Hightest,其次是script标签所请求的脚本文件,当script带有defer或async的异步属性时,其优先级就会降低到Low。可以通过浏览器控制台查看资源的优先级(priority优先级选项默认不显示,可以在开发者工具网络面板中右键点击列标题来启用优先级列):
当页面的资源对用户来说比较重要,又被默认分配为较低优先级时,就可以使用资源的预处理或预连接,如果仅需要浏览器处理完一些任务之后,再去提取某些资源,就可以使用资源的欲提取。
(1)预加载
预加载应该是我们常听说的,可以使用<link ref="preload">
来告诉浏览器当前指定的资源应该具有更高的优先级,需要尽快开始加载资源:
<link ref="preload" as="script" href="important.js">
这里我们给link标签指定了一个as属性,它会告诉浏览器所要加载的资源的类型,当前需要加载的资源必须是这个指定类型的资源,不然不会进行预加载。需要注意的是,<link ref="preload">
是浏览器的强制性指令,preload后浏览器就必定去预加载相应的资源。使用时需要仔细测试,确保不会因为使用它而意外导致资源加载2次。
字体资源的预加载就是一个很好的例子,当使用非系统字体时,需要引入字体文件,字体文件通常都位于页面加载的CSS文件的末尾,为了减少用户等待站点文本内容的时间,以及避免系统字体与样式中定义的字体之间应用时的闪烁,可以在HTML中使用<link rel ="preload">
让浏览器知道样式文件中需要加载的字体资源:
<link ref="preload" as="font" crossorign="crossorign" type="font/woff2" href="font.woff2">
需要注意,这里的crossorign属性很重要,如果缺失,浏览器将忽略预加载的字体,并发起一个新的请求。因为浏览器使用匿名请求加载字体,只有使用crossorigin
属性可以使预加载请求匿名。
(2)预连接
我们知道,在较慢的网络环境下建立网络连接是非常耗时的,如果想建立安全连接将更加好事(例如HTTPS连接)。其原因主要是整个过程涉及到了DNS解析、重定向、三次握手过程等。如果能提前完后才能上述操作,那么就能带来更好的用户体验,与此同时,由于建立连接的大部分时间是消耗在等待的时间上,这样也能有效的优化宽度的使用情况。这时我们就可以使用预连接:
<link ref="preconnect" href="https://juejin.cn/">
这里通过<link ref="preconnect">
指令,告诉浏览器当前页面将与站点之间建立连接,希望尽快启动该过程。虽然这么做成本很低,但是会消耗抱回的CPU的时间,特别是在简历HTTPS安全连接时,如果建立好连接的10s之内没有使用该连接,浏览器就会关闭该连接,那么之前所有准备的资源就都浪费了。
除此之外,还有一种和预连接相关的类型<link ref="dns-prefetch">
,也就是DNS预解析,它仅用来处理DNS查询。该属性在浏览器的支持度很高,并且可以明显缩短DNS的查询时间,所以被普遍使用。
流媒体资源的预连接就是一个很好的例子,对于不同来源的流媒体,我们希望在连接阶段节省一些时间但不一定立即开始获取内容。根据页面处理流内容的方式,可能需要等到脚本加载完毕并做好准备后才处理流。一旦准备加载资源,预连接可帮助我们缩短单次往返的等待时间。
(3)预提取
前面所说的预解析和预连接都是试图更快的获取关键的资源,而接下来要说的预提取则是利用机会让某些非关键资源提前获取。
预提取就是根据用户已发生的行为来判断接下来的预期行为,告诉浏览器稍后可能需要的资源,也就是当页面加载完成之后,且在宽带可用的情况下,这些资源将以lowest的优先级进行提取。
从上面的描述中可知,预提取最适合的场景就是为用户的下一步可能的操作做好必要的准备,比如在搜索框搜索内容时,可以预提取结果列表中首个内容的详情页,或者在使用搜索查询是,预提取搜索结果的下一页的内容。