preload 讓加載和解析解耦

TL;DR

  • preload本質:preload 是聲明式的 fetch,能夠改變瀏覽器加載資源的優先級,強制瀏覽器請求資源,同時不阻塞文檔 onload 事件,也所以能夠將 load 事件與腳本解析過程解耦
  • prefetch本質:讓瀏覽器空閒的時候加載下一頁可能須要的資源,一樣的load和解析解耦
  • dns-fetch,讓瀏覽器提早作dns預解析,當靜態資源和html不在同一個域的時候,特別好用
  • async,defer是script的屬性,其讓html解析與下載並行,可是async下載完以後當即執行,而defer是html解析完以後再執行,通常按照順序執行,但聽說不是百分百靠譜

概述

通常寫html頁面,script寫在body結束標籤前,這樣只有當遇到script標籤的時候,纔會加載執行,費加載時間不科學吖!儘管大多數基於標記語言的資源能被瀏覽器的預加載器(Preloader)提早加載,但仍是不盡如人意!css

理想狀況是,先從文檔須要的資源,根據優先級,下載到本地,等到須要的時候,就能夠直接使用或者解析執行!
而後!對!preload就能夠幹這個事!可隨時關注preload的動態,就目前不少現代瀏覽器已經支持!html

preload大白話的意思是,」嗨,瀏覽器!這個資源在這個頁面後面會用到,如今先加載它吧。「git

好處

好處遠不止上面的:github

  • 本質!preload 是聲明式的 fetch,能夠改變瀏覽器加載資源的優先級,強制瀏覽器請求資源,同時不阻塞文檔 onload 事件,也所以能夠將 load 事件與腳本解析過程解耦
  • 資源的提早加載。<link rel="preload" href="late_discovered_thing.js" as="script">
  • 字體的提早加載。<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
  • 動態加載,但不執行。加載某一資源但卻不想當即執行它,而是想在特定的時機執行。後面細說代碼。
  • 基於標記語言的異步加載。<link rel="preload" as="style" href="asyncstyle.css" onload="this.rel='stylesheet'">,加載完以後就能夠應用到文檔裏了,script也同理,這裏的onload是指window的onload事件,在加一些統計腳本的時候挺合適,不影響頁面的onload,<link rel="preload" as="script" href="async_script.js" onload="var script = document.createElement('script'); script.src = this.href; document.body.appendChild(script);">
  • 響應式加載。preload是在link標籤上,也就是還能夠配合media屬性,能讓瀏覽器加載本身須要的資源。<link rel="preload" as="image" href="map.png" media="(max-width: 600px)"> <link rel="preload" as="script" href="map.js" media="(min-width: 601px)">
  • 檢測瀏覽器是否是支持preload,var isSupportPreload = document.createElement("link").relList && document.createElement("link").relList.supports('preload')

怎麼使用preload

先說說link標籤

先說下link標籤的使用。segmentfault

  • link規定了外部資源與當前文檔的關係!
  • 因而link有不可或缺的兩個屬性,href外部資源的路徑,rel外部資源與當前文檔的關係,rel其實relation的縮寫,但由於多數用於css,因此rel是stylesheet的時候,是能夠省略的
  • link標籤只能出如今head
  • 有全局屬性和onload事件,onload事件是指文檔全部資源加載完以後
  • media:這個屬性規定了外部資源適用的媒體類型。它的值必須是"媒體查詢"。這個屬性使得用戶代理能選擇最適合設備運行的媒體類型。<link rel="stylesheet" media="(max-width: 800px)" href="example.css" />
  • type這個屬性被用於定義連接的內容的類型。這個屬性的值應該是像text/html,text/css等MIME類型。這個屬性經常使用的用法是定義連接的樣式表,最經常使用的值是代表了CSS的text/css。

preload是在link上的

  • 使用preload很簡單,就是link的rel="preload",href是仍然是資源路徑,而後加上as來講明加載的內容的類型就能夠了,經常使用的"script" "style" "image" "media" "document"
  • preload加載字體的時候,crossorigin 屬性是必須的,即使是字體資源在自家服務器上,由於用戶代理必須採用匿名模式來獲取字體資源。type 屬性能夠確保瀏覽器只獲取本身支持的資源。好比Chrome 支持 WOFF2,看到這個就下載了,遇到不識別的類型就忽略
<!-- js -->
<link rel="preload" href="static.js" as="script" onload="preloadFinished()">
<!-- css -->
<link rel="preload" href="static.css" as="style" onload="preloadFinished()">
<!-- 字體,注意crossorigin和type的增長 -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
複製代碼

細說,動態加載,但不執行

其實動態加載就是插入帶preload的link,執行的時候,動態的建立script。瀏覽器

function loadScript(url){
    var link = document.createElement("link");
    link.href = url
    link.rel = "preload";
    link.as = "script";
    document.head.appendChild(link);
}
function execScript(url){
    var script = document.createElement("script");
    script.src = url;
    document.body.appendChild(script);
}
// 加載這個js,但不執行
loadScript("myscript.js")
// 某個時機執行
setTimeout(function(){
    execScript("myscript.js")
},1000)

複製代碼

preload的坑

注意吖,不是說加載了就是執行!!!!!
也就是preload只管加載!!!
換句話說,你買東西,preload至關於快遞到你家門口了,可是你只有拆了包裹纔算是使用!!!
代碼的體現就是,之前的<link href="xx.css"><script src="xxx.js">仍是要寫在相應的位置的!
而後在head頭裏加上<link rel="preload" href="xx.css" as="style"><link rel="preload" href="xxx.js" as="script">,preload是錦上添花的!安全

瀏覽器加載機制

我以爲吧,先去知道瀏覽器加載機制以後,才能更加體會到preload的美!服務器

這邊簡單的總結下,瀏覽器的加載機制:app

  • 資源分類。html,css,js...
  • 安全策略檢查。是否加載某處的資源
  • 資源優先級計算。html、css、font資源 => preload資源、script、xhr請求 => 圖片、語音、視頻 => prefetch預讀取的資源(多用於dns)
  • 綜合安全策略和優先級,開始下載資源
  • 谷歌控制檯查看資源優先級的方法:打開開發者工具 -> 點擊network -> 刷新頁面 -> 在出現的表格的表頭那行右擊(就是Name,type,size...)選擇Priority

prefetch與preload

prefetch至關於說,「嗨,瀏覽器,下個頁面可能要用到這個資源,你閒着無聊就幫我加載下唄~」。 用法跟preload差不離,link的rel="prefetch"異步

和preload區別:

  • preload是讓瀏覽器提早加載當前頁面比較重要的資源,,prefetch是讓瀏覽器沒活的時候加載下個頁面可能用到的資源
  • prefetch並無同域的限制,但preload有
  • 都不會影響onload事件,準備說有點load事件和解析解耦的感受
  • 當頁面上使用到這個資源時候 preload 資源還沒下載完,這時候不會形成二次下載,會等待第一次下載並執行腳本。prefetch差很少吧。
  • 對於 preload 來講,一旦頁面關閉了,它就會當即中止 preload 獲取資源,而對於 prefetch 資源,即便頁面關閉,prefetch 發起的請求仍會進行不會中斷。

隨手說下dns-prefetch

先說域名只是服務器ip地址的美化,也就是雖然請求域名,但實際是先請求dns服務器,dns服務器返回域名所表明的真正的服務器ip,瀏覽器再向服務器發送請求。
dns-prefetch就是讓瀏覽器先將域名發給dns服務器,讓瀏覽器知道,域名所指的真正的服務器,以後在發送請求的時候,就直接發給服務器了。
簡單的一行就能讓支持的瀏覽器提早解析DNS。也就是說在瀏覽器請求資源時,DNS查詢就已經準備好了。

使用方式<link rel="dns-prefetch" href="//example.com">

使用場景:

  • 項目的靜態資源和html不在同一個域上
  • 有重定向的域名

還有async,defer

直接引用這個回答 ,當瀏覽器碰到 script 腳本的時候:

  • 沒有 defer 或 async,瀏覽器會當即加載並執行指定的腳本,「當即」指的是在渲染該 script 標籤之下的文檔元素以前,也就是說不等待後續載入的文檔元素,讀到就加載並執行。<script src="script.js"></script>
  • 有 async,加載和渲染後續文檔元素的過程將和 script.js 的加載與執行並行進行(異步)。<script async src="script.js"></script>
  • 有 defer,加載後續文檔元素的過程將和 script.js 的加載並行進行(異步),可是 script.js 的執行要在全部元素解析完成以後,DOMContentLoaded 事件觸發以前完成。<script defer src="myscript.js"></script>

不知道是誰的圖片

preload的好處
w3c的preload,一眼能夠看到支持
瀏覽器加載機制
prefetch和preload
一籮筐的預取技術

相關文章
相關標籤/搜索