溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用preload預加載頁面資源時注意事項

發(fā)布時間:2020-10-04 14:40:03 來源:腳本之家 閱讀:128 作者:螞蟻金服數(shù)據(jù)體驗技術團隊 欄目:web開發(fā)

preload 提供了一種聲明式的命令,讓瀏覽器提前加載指定資源(加載后并不執(zhí)行),在需要執(zhí)行的時候再執(zhí)行。提供的好處主要是

將加載和執(zhí)行分離開,可不阻塞渲染和 document 的 onload 事件

提前加載指定資源,不再出現(xiàn)依賴的 font 字體隔了一段時間才刷出

如何使用 preload

使用 link 標簽創(chuàng)建
<!-- 使用 link 標簽靜態(tài)標記需要預加載的資源 -->
<link rel="preload" href="/path/to/style.css" rel="external nofollow" as="style">
<!-- 或使用腳本動態(tài)創(chuàng)建一個 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>
使用 HTTP 響應頭的 Link 字段創(chuàng)建
Link: <https://example.com/other/styles.css>; rel=preload; as=style

如我們常用到的 antd 會依賴一個 CDN 上的 font.js 字體文件,我們可以設置為提前加載,以及有一些模塊雖然是按需異步加載,但在某些場景下知道其必定會加載的,則可以設置 preload 進行預加載,如:

<link rel="preload" as="font"  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
<link rel="preload" as="script"  rel="external nofollow" >
<link rel="preload" as="script"  rel="external nofollow" >

如何判斷瀏覽器是否支持 preload

目前我們支持的瀏覽器主要為高版本 Chrome,所以可放心使用 preload 技術。 其他環(huán)境在 caniuse.com 上查到的支持情況如下:

使用preload預加載頁面資源時注意事項

在不支持 preload 的瀏覽器環(huán)境中,會忽略對應的 link 標簽,而若需要做特征檢測的話,則:

const isPreloadSupported = () => {
const link = document.createElement('link');
const relList = link.relList;
if (!relList || !relList.supports) {
return false;
}
return relList.supports('preload');
};

如何區(qū)分 preload 和 prefetch

preload 是告訴瀏覽器頁面必定需要的資源,瀏覽器一定會加載這些資源;

prefetch 是告訴瀏覽器頁面可能需要的資源,瀏覽器不一定會加載這些資源。

preload 是確認會加載指定資源,如在我們的場景中,x-report.js 初始化后一定會加載 PcCommon.js 和 TabsPc.js, 則可以預先 preload 這些資源;

prefetch 是預測會加載指定資源,如在我們的場景中,我們在頁面加載后會初始化首屏組件,當用戶滾動頁面時,會拉取第二屏的組件,若能預測用戶行為,則可以 prefetch 下一屏的組件。

preload 將提升資源加載的優(yōu)先級

使用 preload 前,在遇到資源依賴時進行加載:

使用preload預加載頁面資源時注意事項

使用 preload 后,不管資源是否使用都將提前加載:

使用preload預加載頁面資源時注意事項

可以看到,preload 的資源加載順序將被提前:

使用preload預加載頁面資源時注意事項

避免濫用 preload

使用 preload 后,Chrome 會有一個警告:

使用preload預加載頁面資源時注意事項

如上文所言,若不確定資源是必定會加載的,則不要錯誤使用 preload,以免本末倒置,給頁面帶來更沉重的負擔。

當然,可以在 PC 中使用 preload 來刷新資源的緩存,但在移動端則需要特別慎重,因為可能會浪費用戶的帶寬。

避免混用 preload 和 prefetch

preload 和 prefetch 混用的話,并不會復用資源,而是會重復加載。

<link rel="preload"  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" as="font">
<link rel="prefetch"  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" as="font">

使用 preload 和 prefetch 的邏輯可能不是寫到一起,但一旦發(fā)生對用一資源 preload 或 prefetch 的話,會帶來雙倍的網絡請求,這點通過 Chrome 控制臺的網絡面板就能甄別:

使用preload預加載頁面資源時注意事項

避免錯用 preload 加載跨域資源

若 css 中有應用于已渲染到 DOM 樹的元素的選擇器,且設置了 @font-face 規(guī)則時,會觸發(fā)字體文件的加載。 而字體文件加載中時,DOM 中的這些元素,是處于不可見的狀態(tài)。對已知必加載的 font 文件進行預加載,除了有性能提升外,更有體驗優(yōu)化的效果。

在我們的場景中,已知 antd.css 會依賴 font 文件,所以我們可以對這個字體文件進行 preload:

<link rel="preload" as="font"  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >

然而我發(fā)現(xiàn)這個文件加載了兩次:

使用preload預加載頁面資源時注意事項

使用preload預加載頁面資源時注意事項

使用preload預加載頁面資源時注意事項

原因是對跨域的文件進行 preload 的時候,我們必須加上 crossorigin 屬性:

<link rel="preload" as="font" crossorigin  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >

再看一下網絡請求,就變成一條了。

W3 規(guī)范是這么解釋的:

Preload links for CORS enabled resources, such as fonts or images with a crossorigin attribute, must also include a crossorigin attribute, in order for the resource to be properly used.

那為何會有兩條請求,且優(yōu)先級不一致,又沒有命中緩存呢?這就得引出下一個話題來解釋了。

不同資源加載的優(yōu)先級規(guī)則

我們先來看一張圖:

使用preload預加載頁面資源時注意事項

這張表詳見:Chrome Resource Priorities and Scheduling

這張圖表示的是,在 Chrome 46 以后的版本中,不同的資源在瀏覽器渲染的不同階段進行加載的優(yōu)先級。 在這里,我們只需要關注 DevTools Priority 體現(xiàn)的優(yōu)先級,一共分成五個級別:

Highest 最高

Hight 高

Medium 中等

Low 低

Lowest 最低

使用preload預加載頁面資源時注意事項

html 主要資源,其優(yōu)先級是最高的

使用preload預加載頁面資源時注意事項

使用preload預加載頁面資源時注意事項

css 樣式資源,其優(yōu)先級也是最高的

使用preload預加載頁面資源時注意事項

CSS(match) 指的是對已有的 DOM 具備規(guī)則的有效的樣式文件。

使用preload預加載頁面資源時注意事項

script 腳本資源,優(yōu)先級不一

使用preload預加載頁面資源時注意事項

使用preload預加載頁面資源時注意事項

前三個 js 文件是寫死在 html 中的靜態(tài)資源依賴,后三個 js 文件是根據(jù)首屏按需異步加載的組件資源依賴,這正驗證了這個規(guī)則。

font 字體資源,優(yōu)先級不一

使用preload預加載頁面資源時注意事項

使用preload預加載頁面資源時注意事項

樣式文件中有一個 @font-face 依賴一個 font 文件,樣式文件中依賴的字體文件加載的優(yōu)先級是 Highest; 在使用 preload 預加載這個 font 文件時,若不指定 crossorigin 屬性(即使同源),則會采用匿名模式的 CORS 去加載,優(yōu)先級是 High,看下圖對比: 第一條 High 優(yōu)先級也就是 preload 的請求:

使用preload預加載頁面資源時注意事項

第二條 Highest 也就是樣式引入的請求:

使用preload預加載頁面資源時注意事項

可以看到,在 preload 的請求中,缺少了一個 origin 的請求頭字段,表示這個請求是匿名的請求。 讓這兩個請求能共用緩存的話,目前的解法是給 preload 加上 crossorigin 屬性,這樣請求頭會帶上 origin, 且與樣式引入的請求同源,從而做到命中緩存:

<link rel="preload" as="font" crossorigin  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >

這么請求就只剩一個:

使用preload預加載頁面資源時注意事項

使用preload預加載頁面資源時注意事項

在網絡瀑布流圖中,也顯示成功預加載且后續(xù)命中緩存不再二次加載:

使用preload預加載頁面資源時注意事項

總結

preload 是個好東西,能告訴瀏覽器提前加載當前頁面必須的資源,將加載與解析執(zhí)行分離開,做得好可以對首次渲染帶來不小的提升,但要避免濫用,區(qū)分其與 prefetch 的關系,且需要知道 preload 不同資源時的網絡優(yōu)先級差異。

preload 加載頁面必需的資源如 CDN 上的字體文件,與 prefetch 預測加載下一屏數(shù)據(jù),興許是個不錯的組合。

更多關于preload預加載頁面的文章大家可以看看下面的相關鏈接

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI