您好,登錄后才能下訂單哦!
preload 提供了一種聲明式的命令,讓瀏覽器提前加載指定資源(加載后并不執行),在需要執行的時候再執行。提供的好處主要是
將加載和執行分離開,可不阻塞渲染和 document 的 onload 事件
提前加載指定資源,不再出現依賴的 font 字體隔了一段時間才刷出
<!-- 使用 link 標簽靜態標記需要預加載的資源 --> <link rel="preload" href="/path/to/style.css" rel="external nofollow" 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>
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" >
目前我們支持的瀏覽器主要為高版本 Chrome,所以可放心使用 preload 技術。 其他環境在 caniuse.com 上查到的支持情況如下:
在不支持 preload 的瀏覽器環境中,會忽略對應的 link 標簽,而若需要做特征檢測的話,則:
const isPreloadSupported = () => { const link = document.createElement('link'); const relList = link.relList; if (!relList || !relList.supports) { return false; } return relList.supports('preload'); };
preload 是告訴瀏覽器頁面必定需要的資源,瀏覽器一定會加載這些資源;
prefetch 是告訴瀏覽器頁面可能需要的資源,瀏覽器不一定會加載這些資源。
preload 是確認會加載指定資源,如在我們的場景中,x-report.js 初始化后一定會加載 PcCommon.js 和 TabsPc.js, 則可以預先 preload 這些資源;
prefetch 是預測會加載指定資源,如在我們的場景中,我們在頁面加載后會初始化首屏組件,當用戶滾動頁面時,會拉取第二屏的組件,若能預測用戶行為,則可以 prefetch 下一屏的組件。
使用 preload 前,在遇到資源依賴時進行加載:
使用 preload 后,不管資源是否使用都將提前加載:
可以看到,preload 的資源加載順序將被提前:
使用 preload 后,Chrome 會有一個警告:
如上文所言,若不確定資源是必定會加載的,則不要錯誤使用 preload,以免本末倒置,給頁面帶來更沉重的負擔。
當然,可以在 PC 中使用 preload 來刷新資源的緩存,但在移動端則需要特別慎重,因為可能會浪費用戶的帶寬。
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 的邏輯可能不是寫到一起,但一旦發生對用一資源 preload 或 prefetch 的話,會帶來雙倍的網絡請求,這點通過 Chrome 控制臺的網絡面板就能甄別:
若 css 中有應用于已渲染到 DOM 樹的元素的選擇器,且設置了 @font-face 規則時,會觸發字體文件的加載。 而字體文件加載中時,DOM 中的這些元素,是處于不可見的狀態。對已知必加載的 font 文件進行預加載,除了有性能提升外,更有體驗優化的效果。
在我們的場景中,已知 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" >
然而我發現這個文件加載了兩次:
原因是對跨域的文件進行 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 規范是這么解釋的:
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.
那為何會有兩條請求,且優先級不一致,又沒有命中緩存呢?這就得引出下一個話題來解釋了。
我們先來看一張圖:
這張表詳見:Chrome Resource Priorities and Scheduling
這張圖表示的是,在 Chrome 46 以后的版本中,不同的資源在瀏覽器渲染的不同階段進行加載的優先級。 在這里,我們只需要關注 DevTools Priority 體現的優先級,一共分成五個級別:
Highest 最高
Hight 高
Medium 中等
Low 低
Lowest 最低
CSS(match) 指的是對已有的 DOM 具備規則的有效的樣式文件。
前三個 js 文件是寫死在 html 中的靜態資源依賴,后三個 js 文件是根據首屏按需異步加載的組件資源依賴,這正驗證了這個規則。
樣式文件中有一個 @font-face 依賴一個 font 文件,樣式文件中依賴的字體文件加載的優先級是 Highest; 在使用 preload 預加載這個 font 文件時,若不指定 crossorigin 屬性(即使同源),則會采用匿名模式的 CORS 去加載,優先級是 High,看下圖對比: 第一條 High 優先級也就是 preload 的請求:
第二條 Highest 也就是樣式引入的請求:
可以看到,在 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 是個好東西,能告訴瀏覽器提前加載當前頁面必須的資源,將加載與解析執行分離開,做得好可以對首次渲染帶來不小的提升,但要避免濫用,區分其與 prefetch 的關系,且需要知道 preload 不同資源時的網絡優先級差異。
preload 加載頁面必需的資源如 CDN 上的字體文件,與 prefetch 預測加載下一屏數據,興許是個不錯的組合。
更多關于preload預加載頁面的文章大家可以看看下面的相關鏈接
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。