天天看點

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

浏覽器裡并不是每一個資源加載都很重要。

為了達到重要的資源先加載,浏覽器有試探法,嘗試對資源進行權重配置設定,例如CSS會在腳本和圖檔之前先加載。

因為浏覽器在試探權重配置設定,是以并不總是配置設定的很正确,通常因為沒有足夠的資訊,浏覽器可能做出錯誤的決定。

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

預設優先級

如前所述,浏覽器根據它們的重要程度為不同類型的資源配置設定不同的相對優先級。 像頁面的

<head>

中的

<script>

标記将以"高優先級(High priority)"(CSS是"最高優先級(Highest priority)")加載到Chrome中,但如果它具有async屬性,則該優先級将更改為"低(Low priority)"(意味着它可以加載并異步運作)。

在檢視站點的加載性能時,優先級變得很重要。 除了

測量

分析關鍵渲染路徑

的常用技術之外,了解Chrome對每種資源的優先級配置設定也很有用。

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

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

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開發者工具的控制台中觸發警告,是以請務必留意這些!

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

圖中顯示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">           

在這種情況下,我們讓浏覽器知道我們打算連接配接到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">

用例:知道資源會從哪裡來,但不知道最終擷取什麼資源

有時您知道将從給定的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>           

事情上,這會導緻樣式表被加載兩次(盡管第二個可能命中緩存),一次是預設的最高優先級,一次是最低優先級:

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

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

<link rel ="preload">

<link rel ="preconnect">

<link rel ="prefetch">

(以及

<link rel ="dns-prefetch">

)提供了一種很好的聲明方式 讓浏覽器提前了預加載資源,并在合适的時候使用它們。