前端資源加載優先級[譯]

摘要: 瀏覽器裏並不是每一個資源加載都很重要。 爲了達到重要的資源先加載,瀏覽器有試探法,嘗試對資源進行權重分配,例如CSS會在腳本和圖片之前先加載。 因爲瀏覽器在試探權重分配,所以並不總是分配的很正確,通常因爲沒有足夠的信息,瀏覽器可能做出錯誤的決定。

瀏覽器裏並不是每一個資源加載都很重要。

爲了達到重要的資源先加載,瀏覽器有試探法,嘗試對資源進行權重分配,例如CSS會在腳本和圖片之前先加載。

因爲瀏覽器在試探權重分配,所以並不總是分配的很正確,通常因爲沒有足夠的信息,瀏覽器可能做出錯誤的決定。

本文將介紹如何在現代瀏覽器中以代碼的形式來調整資源加載的優先級。

默認優先級
如前所述,瀏覽器根據它們的重要程度爲不同類型的資源分配不同的相對優先級。 像頁面的<head>中的<script>標記將以"高優先級(High priority)"(CSS是"最高優先級(Highest priority)")加載到Chrome中,但如果它具有async屬性,則該優先級將更改爲"低(Low priority)"(意味着它可以加載並異步運行)。

在查看站點的加載性能時,優先級變得很重要。 除了測量和分析關鍵渲染路徑的常用技術之外,瞭解Chrome對每種資源的優先級分配也很有用。

您可以在Chrome開發者工具的“網絡”面板中找到它。 這是它的樣子:

res_prio_priorities
Chrome開發者工具中網絡面板中的優先級。 如果沒有看到該列,您可以通過右鍵單擊列標題來啓用“優先級”列。

優先級使您瞭解瀏覽器處理每個資源的相對重要性。 請記住,微妙的差異足以讓瀏覽器分配不同的優先級; 例如,作爲初始渲染的一部分的圖像優先於高於從屏幕外開始的圖像。 如果您對優先級感到好奇,Addy Osmani撰寫的這篇文章將深入探討Chrome的優先級。

如果您發現資源加載的優先級與您想要的不同,您會怎麼做?

本文展示了三種不同的聲明性解決方案,它們都是相對較新的<link>類型。 如果您的資源對用戶體驗至關重要,但加載的優先級過低,則可以嘗試通過以下兩種方式之一進行修復:“預加載(Preload)”或“預鏈接(Preconnect)”。 另一方面,如果您希望瀏覽器在完成處理其他內容時獲取某些資源,請嘗試“預獲取(Prefetch)”。

預加載(Preload)
<link rel="preload">通知瀏覽器接下來可能用到的資源,並儘快開始加載資源。 你可以像這樣使用:

<link rel="preload" as="script" href="super-important.js">
<link rel="preload" as="style" href="critical.css">
如你期望,"as"告訴瀏覽器資源類型。你要通過as設置正確的類型,否則瀏覽器不會使用預加載的資源。 瀏覽器在空閒的時候會去加載相應的資源,並在合適的時候使用它們。

<link rel="preload">是瀏覽器的強制性指令,preload後瀏覽器就必定去預加載相應的資源。使用時需要仔細測試,確保您不會因爲使用它而意外導致任何資源加載2次。

使用<link rel="preload">獲取但在3秒內未被當前頁面使用的資源將在Chrome開發者工具的控制檯中觸發警告,因此請務必留意這些!

image
圖中顯示unused.js通過預加載進行了資源加載,但是接下來並沒有使用,如果用不到的資源最好不要使用預加載

用例:字體
字體資源是預獲取的一個很好的例子

爲了減少用戶等待站點文本內容的時間,以及避免系統字體與樣式中定義的字體之間應用時的閃爍,您可以在HTML中使用<link rel ="preload"> 讓瀏覽器知道樣式文件中需要加載的字體資源。

<link rel="preload" as="font" crossorigin="crossorigin" type="font/woff2" href="myfont.woff2">
請注意,使用crossorigin很重要; 如果沒有此屬性,瀏覽器將忽略預加載的字體,併發起一個新的請求。 這是因爲瀏覽器使用匿名請求加載字體,也只有使用crossorigin屬性使預加載請求匿名。

警告:如果您使用的是CDN,例如Google字體,請確保您預加載的字體文件與CSS中的字體文件匹配,由於unicode範圍,權重和字體變體,這可能很棘手。 字體也可以定期更新,如果你預加載了一箇舊版本的字體,但在樣式文件中使用了新版本的字符,則最終可能會下載相同字體的兩個版本並浪費用戶的帶寬。 這種情況請考慮使用<link rel ="preconnect">。

用例:關鍵路徑CSS和JavaScript
在談論頁面性能時,一個有用的概念是“關鍵路徑”。 關鍵路徑是指在初始渲染之前必須加載的資源。 這些資源(如CSS)對於獲取用戶屏幕上的第一個像素至關重要。

以前,建議將此內容內嵌到您的HTML中。 但是,在多頁,服務器端呈現的場景中,這很快就會變成大量浪費的字節。 它還使版本控制變得更加困難,因爲關鍵代碼中的任何更改都會使任何內聯頁面無效。

<link rel ="preload">允許您保留單個文件版本控制和緩存的好處,同時爲您提供儘快請求資源的機制。

<link rel="preload" as="script" href="super-important.js">
<link rel="preload" as="style" href="critical.css">
預加載缺點:需要額外的往返。 這個額外的往返來自於瀏覽器先獲取HTML,然後它才能從HTML中找出要加載的下一個資源。

解決額外往返的一種方法是使用HTTP / 2推送,在這種情況下,您可以將關鍵資源附加到和發送HTML的同一連接。 這可以保證用戶瀏覽器檢索HTML和開始下載關鍵資源之間沒有停頓時間。 但是,在使用HTTP / 2推送時要小心,因爲這是控制用戶帶寬使用的一種非常有力的方式,並且留給瀏覽器做決定的空間很小,例如不檢索已經在緩存中的文件!

預連接(Preconnect)
<link rel ="preconnect">通知瀏覽器您的頁面打算與另一個來源建立連接,並且您希望該過程儘快啓動。

建立連接通常需要在慢速網絡中佔用大量時間,特別是在涉及安全連接時,因爲它可能涉及DNS查找,重定向以及到處理用戶請求的最終服務器的多次往返。 提前處理所有這些可以使您的應用程序對用戶感覺更加快捷,而不會對帶寬的使用產生負面影響。 建立連接的大部分時間都花在等待上,而不是交換數據。

告知瀏覽器您的意圖就像在頁面中添加鏈接標記一樣簡單:

<link rel="preconnect" href="https://example.com"&gt;
在這種情況下,我們讓瀏覽器知道我們打算連接到example.com並從那裏檢索內容。

請記住,雖然<link rel ="preconnect">輕量,但它仍然佔用寶貴的CPU時間,特別是在安全連接上。 如果在10秒內沒有使用連接,這會特別糟糕,因爲瀏覽器會關閉它,浪費所有早期的連接工作。

一般情況下,嘗試使用<link rel ="preload">,因爲它是一個更全面的性能優化方案,其它更復雜的情況,你需要使用<link rel ="preconnect">。

注意:實際上還有另一個與連接相關的<link>類型:<link rel ="dns-prefetch">。 這僅處理DNS查找,它是<link rel ="preconnect">的一小部分。<link rel ="dns-prefetch">具有更廣泛的瀏覽器支持,因此它可以作爲一個很好的後備。 您可以用相同的方式使用它:<link rel ="dns-prefetch" href ="https://example.com"&gt;

用例:知道資源會從哪裏來,但不知道最終獲取什麼資源
有時您知道將從給定的CDN中檢索資源,但並不知道完整路徑。 根據用戶的使用情況或其它運行時特徵,從CDN上獲取一個或多個資源。

在這種情況下,如果您要獲取的資源很重要,您可能希望通過預連接到服務器來節省儘可能多的時間。 瀏覽器不會在需要之前開始提取文件(也就是說,一旦請求以某種方式從您的頁面發出),但至少它可以提前處理連接,從而使用戶無需等待幾次往返。

用例:流媒體
不同來源的流媒體,您可能希望在連接階段節省一些時間但不一定立即開始獲取內容。

根據頁面處理流內容的方式,您可能需要等到腳本加載完畢並做好準備後才處理流。 一旦準備加載資源,預連接可幫助您縮短單次往返的等待時間。

預獲取(Prefetch)
它通過向瀏覽器通知將來需要的資源來加速頁面的後續展現,例如,如果用戶採取了我們期望的操作,則我們可以提前加載稍後可能需要的東西。 當前頁面加載並且有可用帶寬時,這些資源在Chrome中以最低優先級獲取。

這意味着預獲取最適合提前做好用戶下一步可能做的事情的準備,例如檢索結果列表中的第一個產品詳細信息頁面,或檢索分頁內容中的下一頁。

<link rel="prefetch" href="page-2.html">
但請記住,預取不會遞歸地起作用。 在上面的示例中, 除非您明確預獲取page-2.html中的內容,否則瀏覽器不會提前下載page-2.html所需的任何資源。

預獲取(Prefetch)不會覆蓋
請務必注意,不能使用<link rel ="prefetch">作爲降低現有資源優先級的方法。 在下面的HTML中,您可能認爲在預取中聲明optional.css會降低後續<link rel ="stylesheet">的優先級:

<html>
<head>
<link rel="prefetch" href="optional.css">
<link rel="stylesheet" href="optional.css">
</head>
<body>
Hello!
</body>
</html>
事情上,這會導致樣式表被加載兩次(儘管第二個可能命中緩存),一次是默認的最高優先級,一次是最低優先級:

image
資源多次加載對用戶來說是不好的。 在這種情況下,他們不僅要等待渲染阻止CSS,而且還可能通過兩次下載文件來浪費他們的帶寬。 務必徹底分析您的網絡請求,並留意任何相同資源的多次加載!

<link rel ="preload">,<link rel ="preconnect">和<link rel ="prefetch">(以及<link rel ="dns-prefetch">)提供了一種很好的聲明方式 讓瀏覽器提前了預加載資源,並在合適的時候使用它們。請添加鏈接描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章