Web 性能優(yōu)化:Preload與Prefetch的使用及在 Chrome 中的優(yōu)先級

摘要: 理解Preload與Prefetch。

Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有馅巷。

這是 Web 性能優(yōu)化的第 6 篇服傍,上一篇在下面看點擊查看:

今天票灰,我們將深入研究Chrome 的網(wǎng)絡(luò)棧蔬墩,以明確 web 加載原語(如<link rel= preload > & <link rel= prefetch >) 背后的工作原理斤贰,以便你能夠更有效地使用它們篡帕。

如其他文章所述殖侵,preload 是一個聲明式 fetch,可以強制瀏覽器在不阻塞 documentonload 事件的情況下請求資源镰烧。

Prefetch 告訴瀏覽器這個資源將來可能需要拢军,但是什么時間加載這個資源是由瀏覽器來決定的。

在預(yù)加載(perload)之前怔鳖,網(wǎng)絡(luò)請求從這里開始茉唉,預(yù)加載之后,它在解析時從左向右移動

使用預(yù)加載(perload)的一些案例

在詳細介紹 預(yù)加載(perload) 之前败砂,先來看看一些使用 預(yù)加載(perload) 的案例赌渣。

Housing.com 在對他們的漸進式 Web 應(yīng)用程序的腳本轉(zhuǎn)用 proload 看到大約縮短了10%的可交互時間

Shopify 使用 [preload 加載 Web字體](https://www.bramstein.com/writing/preload-hints-for-web-fo
nts.html)后昌犹,Chrome 桌面版)的文本繪制時間(1.2秒)提高了50%坚芜,這完全解決了他們的文字閃動問題。

左邊:使用 preload斜姥,右邊:不使用 preload

使用<link rel="preload"> 加載字體

Treebo鸿竖,印度最大的旅館網(wǎng)站之一沧竟,在 3G 網(wǎng)絡(luò)下對其桌面版試驗,在對其頂部圖片和主要的 Webpack 打包文件使用 preload 之后缚忧,在首屏繪制和可交互延遲分別減少了 1s悟泵。

同樣的,在對自己的漸進式 Web 應(yīng)用程序主要打包文件使用 preload 之后闪水,F(xiàn)lipkart 在路由解析之前 節(jié)省了大量的主線程空閑時間(在 3G 網(wǎng)絡(luò)下的低性能手機下)糕非。

上面:沒有使用 proload 加載,下面:使用 preload 加載

Chrome 數(shù)據(jù)保護程序團隊發(fā)現(xiàn)球榆,對于那些可以在腳本和 CSS 樣式表上使用 preload 的頁面朽肥,發(fā)現(xiàn)頁面首次繪制時間獲得平均 12% 的速度提升。

對于 prefetch(預(yù)讀取)持钉,它被廣泛使用衡招,在 Google 我們?nèi)杂盟鼇?code>預(yù)讀取一些可以加快 搜索結(jié)果頁面 的渲染的關(guān)鍵資源。

Preload 在大型網(wǎng)站中都有很好運用每强,你可以在本文后面找到更多這些安全始腾。 在此之前,讓我們深入了解網(wǎng)絡(luò)堆棧如何實際處理 預(yù)加載(prefetch)與預(yù)讀取(prefetch)空执。

何時使用 <link rel="preload"> 和 <link rel="prefetch"> 浪箭?

提示:preload 加載資源一般是當(dāng)前頁面需要的,prefetch 一般是其它頁面有可能用到的資源辨绊。

preload 是告訴瀏覽器預(yù)先請求當(dāng)前頁面需要的資源(關(guān)鍵的腳本山林,字體,主要圖片等)邢羔。

prefetch 應(yīng)用場景稍微又些不同 —— 用戶將來可能跳轉(zhuǎn)到其它頁面需要使用到的資源驼抹。如果 A 頁面發(fā)起一個 B 頁面的 prefetch 請求,這個資源獲取過程和導(dǎo)航請求可能是同步進行的拜鹤,而如果我們用 preload 的話框冀,頁面 A 離開時它會立即停止。

preloadprefetch 之間敏簿,我們對當(dāng)前頁面或即將跳轉(zhuǎn)的頁面在所需主要資源的問題有了一個解決方案明也。

<link rel="preload"> 和 <link rel="prefetch"> 的緩存行為

當(dāng)資源被 preload 或者 prefetch 后,會從網(wǎng)絡(luò)堆棧傳輸?shù)?HTTP 緩存并進入渲染器的內(nèi)存緩存惯裕。 如果資源可以被緩存(例如温数,存在有效的 cache-control 和 max-age),它將存儲在 HTTP 緩存中蜻势,可用于當(dāng)前和未來的會話撑刺。 如果資源不可緩存,則不會將其存儲在 HTTP 緩存中握玛。 相反够傍,它會被緩存到內(nèi)存緩存中并保持不變直到它被使用甫菠。

Chrome 的網(wǎng)絡(luò)棧中是如何處理 preload 和 prefetch 的優(yōu)先級?

下面是在 Blink 內(nèi)核的 Chrome 46 及更高版本中不同資源的加載優(yōu)先級情況著作權(quán)歸作者所有冕屯。

preload 用 “as” 或者用 “type” 屬性來表示他們請求資源的優(yōu)先級(比如說 preload 使用 as="style" 屬性將獲得最高的優(yōu)先級)寂诱。沒有 “as” 屬性的將被看作異步請求,“Early”意味著在所有未被預(yù)加載的圖片請求之前被請求(“l(fā)ate”意味著之后)

我們來談一下這張表安聘。

腳本根據(jù)它們在文件中的位置是否異步痰洒、延遲或阻塞獲得不同的優(yōu)先級:

  • 網(wǎng)絡(luò)在第一個圖片資源之前阻塞的腳本在網(wǎng)絡(luò)優(yōu)先級中是中級
  • 網(wǎng)絡(luò)在第一個圖片資源之后阻塞的腳本在網(wǎng)絡(luò)優(yōu)先級中是低級
  • 異步/延遲/插入的腳本(無論在什么位置)在網(wǎng)絡(luò)優(yōu)先級中是很低級

圖像在可視窗口中比不在視口中的圖像(具有更高的優(yōu)先級,因此在某種程度上浴韭, Chrome 將會盡量懶加載這些不在視口中的圖片带迟。 較低優(yōu)先級的圖片出現(xiàn)在視口中時,該圖片的優(yōu)先級就會得到提升(但是注意已經(jīng)在布局完成后的圖片優(yōu)先級不會在更改)囱桨。

使用“as”屬性預(yù)加載的資源將具有與它們請求的資源類型相同的資源優(yōu)先級。 例如嗅绰,preload as =“style”將獲得最高優(yōu)先級舍肠,而as =“script”將獲得低優(yōu)先級或中優(yōu)先級。 這些資源也遵循相同的CSP策略(例如腳本受 script-src 約束)窘面。

不帶 “as” 屬性的 preload 的優(yōu)先級將會等同于異步請求翠语。

如果你想了解各種資源加載時的優(yōu)先級屬性,從開發(fā)者工具的 Timeline/Performance 區(qū)域的 Network 區(qū)域都能看到相關(guān)信息:

在 Network 面板下的 “Priority” 部分

當(dāng)頁面 preload 已經(jīng)在 Service Worker 緩存及 HTTP 緩存中的資源時會發(fā)生什么财边?

這各情況來說是比較少的肌括,但通常來說,會是比較好的情況 —— 如果資源沒有超出 HTTP 緩存時間或者 Service Worker 沒有主動重新發(fā)起請求酣难,那么瀏覽器就不會再去請求這個資源了谍夭。

如果資源在 HTTP 緩存中(在SW緩存和網(wǎng)絡(luò)之間),那么 preload 會從相同的資源中獲得緩存命中憨募。

這種加載方式會浪費用戶的帶寬嗎

使用 preload 或 prefetch紧索,可能會浪費用戶的帶寬,特別是在資源沒有緩存的情況下菜谣。

沒有用到的 preload 資源在 Chrome 的 console 里會在 onload 事件 3s 后發(fā)生警告珠漂。

這個警告的原因是,你可能正在使用preload來嘗試為其他資源預(yù)加載并緩存以提高性能尾膊,但是如果這些預(yù)加載的資源沒有被使用媳危,那么你就在毫無理由地做額外的工作。在移動設(shè)備上冈敛,這相當(dāng)于浪費用戶的流量待笑,所以要注意預(yù)加載的內(nèi)容。

什么情況會導(dǎo)致二次獲茸デ础滋觉?

preloadprefetch 是很簡單的工具签夭,你很容易不小心二次獲取。

不要用 “prefetch” 作為 “preload” 的后備方案 椎侠,它們適用于不同的場景第租,常常會導(dǎo)致不符合預(yù)期的二次獲取。使用 preload來獲取當(dāng)前需要任務(wù)否則使用 prefetch 來獲取將來的任務(wù)我纪,不要一起用慎宾。

對 preload 使用 “as” 屬性,不然將不會從中獲益浅悉。

如果在指定要 preload 的內(nèi)容(例如腳本)時未提供有效的“as”趟据,則最終將獲取兩次。

preload 字體不帶 crossorigin 也將會二次獲取, 確保在使用 preload 獲取字體時添加crossorigin 屬性术健,否則將二次下載汹碱。 他這個請求使用匿名的跨域模式。 即使字體與頁面位于同個域 下荞估,也建議使用咳促。也適用于其他域名的獲取(比如說默認(rèn)的異步獲取)。

最后勘伺,雖然它不會導(dǎo)致兩次獲取跪腹,但這通常是一個很好的建議:

不要所有的請求資源都加 preload,用 preload 來告訴瀏覽器一些很被需要的資源,以便讓它提早獲取它們飞醉。

我應(yīng)當(dāng)在頁面頭部所有的資源都加上 preload冲茸?

這是工具的一個很好的例子,而不是規(guī)則缅帘。 preload 的文件數(shù)量取決于加載其他資源時網(wǎng)絡(luò)內(nèi)容轴术、用戶的帶寬和其他網(wǎng)絡(luò)狀況。

盡早 preload 頁面中可能需要的文件钦无,對于腳本膳音,preload 你的密鑰包是很好的,因為它將獲取與執(zhí)行分開铃诬,而僅僅使用 <script async> 不會這樣做祭陷,因為它會阻止窗口的 onload 事件。你可以 preload 圖像趣席、樣式兵志、字體和媒體。最重要的是宣肚,作為一名頁面作者想罕,你可以更好地控制提前獲取頁面所需要的信息。

prefetch 是否具有你應(yīng)該注意的任何魔法屬性? 是的按价,

在 Chrome 中惭适,如果用戶導(dǎo)航離開一個頁面,而對其他頁面的預(yù)取請求仍在進行中楼镐,這些請求將不會被終止癞志。

此外,無論資源的可緩存性如何框产,prefetch 請求在未指定的網(wǎng)絡(luò)堆棧緩存中至少保存 5 分鐘凄杯。

我在 JS 中使用自定義的 “preload”,它跟原本的 rel="preload" 或者 preload 頭部有什么不同秉宿?

preload 解耦從 JS 處理和執(zhí)行中獲取資源戒突。 因此,preload 在標(biāo)記中聲明以被 Chrome preload 掃描器掃描描睦。 這意味著在許多情況下膊存,在 HTML 解析器甚至到達標(biāo)簽之前,將獲取預(yù)加載(具有指示的優(yōu)先級)忱叭,這使它比自定義預(yù)加載實現(xiàn)更強大隔崎。

代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG窑多,花了大量的時間進行l(wèi)og 調(diào)試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具 Fundebug洼滚。

不是可以用 HTTP/2 的服務(wù)器推送來代替 preload 嗎埂息?

當(dāng)你知道資源的精確加載順序時使用推送,并讓 service worker 攔截可能導(dǎo)致再次推送緩存資源的請求遥巴。 使用 preload 可以使資源的開始下載時間更接近初始請求 - 這對所有的資源獲取都有用千康。

我們假設(shè)瀏覽器正在加載一個頁面,頁面中有個 CSS 文件铲掐,CSS 文件又引用一個字體庫拾弃,對于這樣的場景,

若使用 HTTP/2 PUSH摆霉,當(dāng)服務(wù)端獲取到 HTML 文件后豪椿,知道以后客戶端會需要字體文件,它就立即主動地推送這個文件給客戶端携栋,如下圖:

而對于 preload搭盾,服務(wù)端就不會主動地推送字體文件,在瀏覽器獲取到頁面之后發(fā)現(xiàn) preload 字體才會去獲取婉支,如下圖:

雖然推送很有效鸯隅,但它不像 preload 那樣對所有的情況都適應(yīng)。

推送不能用于第三方資源的內(nèi)容向挖,通過立即發(fā)送資源蝌以,它還有效地縮短瀏覽器自身的資源優(yōu)先級情況炕舵。在你明確的知道在做什么時,這應(yīng)該會提高你的應(yīng)用性能跟畅,如果不是很清晰的話咽筋,你也許會損失掉部分的性能。

peload 請求頭是什么碍彭?它與 preload 標(biāo)簽相比如何晤硕?它與 HTTP/2 服務(wù)器推送有什么關(guān)系?

與其他類型的鏈接一樣庇忌,preload 鏈接即可以使用 HTML標(biāo)記 或 HTTP標(biāo)頭舞箍。 在任何一種情況下,preload 鏈接都會指示瀏覽器開始將資源加載到內(nèi)存緩存中皆疹,這表明該頁面有很高可能性使用該資源疏橄,并且不希望等待預(yù)加載掃描程序或解析程序發(fā)現(xiàn)它。

當(dāng)金融時報在它們的網(wǎng)站使用 preload HTTP 頭時略就,他們節(jié)約了大約 1s 的顯示片頭圖片時間捎迫。

1: 沒有使用 preload 2:使用了 preload

你可以使用任何一種形式提供 preload 鏈接,但是你應(yīng)該知道一個重要區(qū)別:如規(guī)范所允許的表牢,許多服務(wù)器在遇到 HTTP 頭的 preload 鏈接時會觸發(fā) HTTP/2 服務(wù)器推送窄绒。 HTTP/2 推送的性能影響不同于普通的預(yù)加載,所以你要確保沒有發(fā)起不必要的推送崔兴。

你可以使用 preload 標(biāo)簽來代替 preload 頭以避免不必要的推送彰导,或者在你的 HTTP 頭上加一個 “nopush” 屬性。

如何判斷 <link rel="preload"> 的支持情況敲茄?

以下的代碼段可以判斷 <link rel=”preload”>支持情況:

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

FilamentGroup 也有一個 preload 檢測器 位谋,作為他們的異步 CSS 加載庫 loadCSS 的一部分。

可以使用 preload 讓CSS樣式立即生效嗎堰燎?

當(dāng)然可以掏父,preload 支持基于異步加載的標(biāo)記,使用 <link rel=”preload”> 的樣式表可以使用 onload 事件立即應(yīng)用于當(dāng)前文檔:

<link rel="preload" href="style.css" onload="this.rel=stylesheet">

preload 還被哪些網(wǎng)站廣泛的應(yīng)用秆剪?

根據(jù) HTTPArchive赊淑,大多數(shù)使用 <link rel =“preload”>的網(wǎng)站使用它來預(yù)加載Web字體,包括 Teen Vogue 和前面提到的 Shopify

而 LifeHacker 和 JCPenny 等其他熱門網(wǎng)站使用它來異步加載CSS(通過Filament Group loadCSS):

然后仅讽,有越來越多的漸進式 Web 應(yīng)用程序(如 Twitter.com mobile膏燃、Flipkart 和Housing)使用它來預(yù)加載當(dāng)前導(dǎo)航所需的腳本(使用PRPL等模式)

其基本思想是以高粒度維護工件(而不是整體捆綁),所以任何應(yīng)用都可以按需加載依賴或者預(yù)加載資源并放在緩存中何什。

當(dāng)前瀏覽器對 preload 和 Prefetch 的支持程序如何

根據(jù) CanIUse组哩,<link rel =“preload”>50% 的支持度, <link rel =“prefetch”>71%

相關(guān)閱讀

關(guān)于Fundebug

Fundebug專注于JavaScript伶贰、微信小程序蛛砰、微信小游戲、支付寶小程序黍衙、React Native泥畅、Node.js和Java線上應(yīng)用實時BUG監(jiān)控。 自從2016年雙十一正式上線琅翻,F(xiàn)undebug累計處理了10億+錯誤事件位仁,付費客戶有Google、360方椎、金山軟件聂抢、百姓網(wǎng)等眾多品牌企業(yè)。歡迎大家免費試用棠众!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末琳疏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子闸拿,更是在濱河造成了極大的恐慌空盼,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件新荤,死亡現(xiàn)場離奇詭異揽趾,居然都是意外死亡,警方通過查閱死者的電腦和手機苛骨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門篱瞎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人智袭,你說我怎么就攤上這事奔缠÷犹В” “怎么了吼野?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長两波。 經(jīng)常有香客問我瞳步,道長,這世上最難降的妖魔是什么腰奋? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任单起,我火速辦了婚禮,結(jié)果婚禮上劣坊,老公的妹妹穿的比我還像新娘嘀倒。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布测蘑。 她就那樣靜靜地躺著灌危,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碳胳。 梳的紋絲不亂的頭發(fā)上勇蝙,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音挨约,去河邊找鬼味混。 笑死,一個胖子當(dāng)著我的面吹牛诫惭,可吹牛的內(nèi)容都是我干的翁锡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贝攒,長吁一口氣:“原來是場噩夢啊……” “哼盗誊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起隘弊,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤哈踱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后梨熙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體开镣,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年咽扇,在試婚紗的時候發(fā)現(xiàn)自己被綠了邪财。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俏竞。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡玷犹,死狀恐怖谣膳,靈堂內(nèi)的尸體忽然破棺而出纪隙,到底是詐尸還是另有隱情垮斯,我是刑警寧澤窗怒,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布姨丈,位于F島的核電站岸蜗,受9級特大地震影響九昧,放射性物質(zhì)發(fā)生泄漏绊袋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一铸鹰、第九天 我趴在偏房一處隱蔽的房頂上張望癌别。 院中可真熱鬧,春花似錦蹋笼、人聲如沸展姐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圾笨。三九已至缤苫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間墅拭,已是汗流浹背活玲。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谍婉,地道東北人舒憾。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像穗熬,于是被迫代替她去往敵國和親镀迂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354