[1]資源優先級
[2]preload
[3]prefetch
前面的話
基于VUE的前端小站改造成SSR伺服器端渲染後,HTML文檔會自動使用preload和prefetch來預加載所需資源,本文将詳細介紹preload和prefetch的使用
資源優先級
在介紹preload和prefetch之前,首先要介紹浏覽器的資源優先級

在Chrome浏覽器中,不同的資源在浏覽器渲染的不同階段進行加載的優先級不同
一共分成五個級别
Highest 最高
Hight 高
Medium 中等
Low 低
Lowest 最低
其中主資源HTML和CSS的優先級最高,其他資源根據情況的不同優先級不一
JS腳本根據它們在檔案中的位置是否異步、延遲或阻塞獲得不同的優先級:
1、網絡在第一個圖檔資源之前阻塞的腳本在網絡優先級中是中級
2、網絡在第一個圖檔資源之後阻塞的腳本在網絡優先級中是低級
3、異步/延遲/插入的腳本(無論在什麼位置)在網絡優先級中是很低級
圖檔(視口可見)将會獲得相對于視口不可見圖檔(低級)的更高的優先級(中級),是以某些程度上 Chrome 将會盡量懶加載這些圖檔。低優先級的圖檔在布局完成被視口發現時,将會獲得優先級提升
preload 使用 “as” 屬性加載的資源将會獲得與資源 “type” 屬性所擁有的相同的優先級。比如說,preload as="style" 将會獲得比 as=“script” 更高的優先級
不帶 “as” 屬性的 preload 的優先級将會等同于異步請求
preload
【定義】
如下所示,preload是link元素中的rel屬性值
<link rel=“preload”>
preload 提供了一種聲明式的指令,讓浏覽器提前加載指定資源(加載後并不執行),需要執行時再執行
這樣做的好處在于:
1、将加載和執行分離開,不阻塞渲染和document的onload事件
2、提前加載指定資源,不再出現依賴的font字型隔了一段時間才刷出的情況
【建立】
使用 link 标簽靜态标記需要預加載的資源
<link rel="preload" href="/path/to/style.css" as="style">
也可以使用腳本動态建立一個 link 标簽後插入到 head 頭部
<script>
const link = document.createElement('link');
link.rel = 'preload';
link.as = 'style';
link.href = '/path/to/style.css';
document.head.appendChild(link);
</script>
【檢測】
在不支援 preload 的浏覽器環境中,會忽略對應的 link 标簽,而若需要做特征檢測的話,則可以使用如下代碼
const isPreloadSupported = () => {
const link = document.createElement('link');
const relList = link.relList;
if (!relList || !relList.supports) {
return false;
}
return relList.supports('preload');
}
【特性】
使用 preload 後,不管資源是否使用都将提前加載。若不确定資源是必定會加載的,則不要錯誤使用 preload,以免本末導緻,給頁面帶來更沉重的負擔
Preload 有 as 屬性,浏覽器可以設定正确的資源加載優先級,這種方式可以確定資源根據其重要性依次加載, 是以,Preload既不會影響重要資源的加載,又不會讓次要資源影響自身的加載;浏覽器能根據 as 的值發送适當的 Accept 頭部資訊;浏覽器通過 as 值能得知資源類型,是以當擷取的資源相同時,浏覽器能夠判斷前面擷取的資源是否能重用
如果忽略 as 屬性,或者錯誤的 as 屬性會使 preload 等同于 XHR 請求,浏覽器不知道加載的是什麼,是以會賦予此類資源非常低的加載優先級
Preload 的與衆不同還展現在 onload 事件上。也就是說可以定義資源加載完畢後的回調函數
<link rel="preload" href="..." as="..." onload="preloadFinished()">
比如,可以使用preload的樣式表立即生效
<link rel="preload" href="style.css" onload="this.rel=stylesheet">
此外,preload 不會阻塞 windows 的 onload 事件
對跨域的檔案進行preload時,必須加上 crossorigin 屬性
<link rel="preload" as="font" crossorigin href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff">
【二次擷取】
1、不使用as屬性
如果對所 preload 的資源不使用明确的 “as” 屬性,将會導緻二次擷取
2、字型檔案
preload 字型不帶 crossorigin 會二次擷取! 確定對 preload 的字型添加 crossorigin 屬性,否則字型檔案會被下載下傳兩次,這個請求使用匿名的跨域模式。這個建議也适用于字型檔案在相同域名下,也适用于其他域名的擷取(比如說預設的異步擷取)
【警告】
沒有用到的 preload 資源在 Chrome 的 console 裡會在 onload 事件 3s 後發生警告
prefetch
如下所示,prefetch是link元素中的rel屬性值
<link rel=“prefetch”>
它的作用是告訴浏覽器加載下一頁面可能會用到的資源,注意,是下一頁面,而不是目前頁面。是以該方法的加載優先級非常低,也就是說該方式的作用是加速下一個頁面的加載速度
【區分】
preload 是告訴浏覽器頁面必定需要的資源,浏覽器一定會加載這些資源
prefetch 是告訴浏覽器頁面可能需要的資源,浏覽器不一定會加載這些資源
在VUE SSR生成的頁面中,首頁的資源均使用preload,而路由對應的資源,則使用prefetch
<link rel="preload" href="./manifest.js" as="script">
<link rel="preload" href="./vendor.js" as="script">
<link rel="preload" href="./app.js" as="script">
<link rel="prefetch" href="./vendor-async.js">
<link rel="prefetch" href="./user.js">
<link rel="prefetch" href="./comment.js">
<link rel="prefetch" href="./category.js">
<link rel="prefetch" href="./post.js">
<link rel="prefetch" href="./home.js">
是以,對于目前頁面很有必要的資源使用 preload,對于可能在将來的頁面中使用的資源使用 prefetch
【不要混用】
preload 和 prefetch 混用的話,并不會複用資源,而是會重複加載
<link rel="preload" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" as="font">
<link rel="prefetch" href="https://at.alicdn.com/t/font_zck90zmlh7hf47vi.woff" as="font">
使用 preload 和 prefetch 的邏輯可能不是寫到一起,但一旦發生對用一資源 preload 或 prefetch 的話,會帶來雙倍的網絡請求
好的代碼像粥一樣,都是用時間熬出來的