前言
最近在研究 vue-cli 3.0生成的工程,在構建后生成的 index.html里面發現了下面這種用法:
前言
最近在研究 vue-cli 3.0生成的工程,在構建后生成的 index.html里面發現了下面這種用法:
這就觸到了本人的知識盲區了,本著掃盲的目的,研究了下 link 標簽,發現這個小東西功能還是挺強大的,上面的就是為了實現預加載功能,懂點兒英文的,一看見preload 就大致知道了。愛掏網 - it200.com
之前也有預加載技術,像 prefetch,subresource 等,關于這兩者和 preload 的區別,這是另外的話題了, 感興趣的可以自己搜一下,不想搜的,你只要知道這兩個跟 preload 相比弱的一逼就行了,就是 prefetch 瀏覽器兼容性方面稍微好一點點,這三個也各有偏重和應用場景,就不詳細介紹了,下面我們就詳細展開preload 這塊。愛掏網 - it200.com
功能介紹:
preload 是一項新的 web 標準,旨在提高性能,讓 FE 對加載的控制更加粒度化。愛掏網 - it200.com它讓開發者有自定義加載邏輯的能力,免受基于腳本的加載器所帶來的性能損耗。愛掏網 - it200.com
preload 一個基本的用法就是提前加載資源,盡管大多數基于標記語言的資源能被瀏覽器的預加載器(preloader)盡早發現,但不是所有的資源都是基于標記語言的,比如一些隱藏在 css 和 js 中的資源(字體,圖片等),當瀏覽器發現頁面需要這些資源時,重新走一遍加載執行渲染的過程,會降低用戶體驗,并且對頁面的渲染 造成延遲;
Preloader 簡介
HTML 解析器在創建 DOM 時如果碰上同步腳本(synchronous script),解析器會停止創建 DOM,轉而去執行腳本。愛掏網 - it200.com所以,如果資源的獲取只發生在解析器創建 DOM時,同步腳本的介入將使網絡處于空置狀態,尤其是對外部腳本資源來說,當然,頁面內的腳本有時也會導致延遲。愛掏網 - it200.com
預加載器(Preloader)的出現就是為了優化這個過程,預加載器通過分析瀏覽器對 HTML 文檔的早期解析結果(這一階段叫做“令牌化(tokenization)”),找到可能包含資源的標簽(tag),并將這些資源的 URL 收集起來。愛掏網 - it200.com令牌化階段的輸出將會送到真正的 HTML 解析器手中,而收集起來的資源 URLs 會和資源類型一起被送到讀取器(fetcher)手中,讀取器會根據這些資源對頁面加載速度的影響進行有次序地加載。愛掏網 - it200.com
預加載的好處:
- 讓瀏覽器提前加載指定資源(這里預加載完成后并不執行),在需要執行的時候在執行,這樣將加載和執行分開,可以不阻塞渲染和 window.onload事件。愛掏網 - it200.com
- 提前預加載指定資源,特別是字體文件,不會再出現 font 字體在頁面渲染出來后,才加載完畢,然后頁面字體閃一下變成預期字體。愛掏網 - it200.com
- 帶有 onload 事件,可以自定義資源在預加載完畢后的回調函數。愛掏網 - it200.com
涉及屬性介紹:
應用場景:
- 包含媒體
元素有一個很棒的特性是它們能夠接受一個media屬性。愛掏網 - it200.com它們可以接受媒體類型或有效的媒體查詢作為屬性值,這將令你能夠使用響應式的預加載!
讓我們來看一個簡單的示例(可以查看Github上的源代碼或在線示例):
Responsive preload example
My site
你可以看到我們在元素中包含了一個media屬性,因此,當用戶在使用較窄屏幕的設備時,較窄的圖片將會被預加載,而在較寬的設備上,較寬的圖片將被預加載。愛掏網 - it200.com然后我們仍需要在header元素上附加合適的圖片——通過Window.matchMedia?/?MediaQueryList?來加以實現(可以查看Testing media queries一文來了解更多信息)。愛掏網 - it200.com
- 字體提前加載
web 字體是較晚才能被發現的關鍵資源中常見的一種。愛掏網 - it200.com但是在用戶體驗對前端來說至關重要的現階段前端開發來說,web 字體對頁面的渲染也是至關重要。愛掏網 - it200.com字體的引用被深埋在 css 中,即便預加載器有提前解析 css,也無法確定包含字體信息的選擇器是否會真正作用在 dom 節點上。愛掏網 - it200.com所以為了減少 FOUT(無樣式字體閃爍,flash of unstyled text )需要預加載字體文件,有了 preload,一行代碼搞定:
NOTE :
crossorigin 屬性在加載字體的時候是必須的,即便字體沒有跨域是在自己公司的服務器上,因為用戶代理必須采用匿名模式來獲取字體資源(為什么會這樣呢?)。愛掏網 - it200.com
type 屬性可以確保瀏覽器只獲取自己支持的資源。愛掏網 - it200.com
- 動態加載,但不執行
另外一個有意思的場景也因為 preload 的出現變得可能——當你想加載某一資源但卻不想執行它。愛掏網 - it200.com比如說,你想在頁面生命周期的某一時刻執行一段腳本,而你無法對這段腳本做任何修改,不可能為它創建一個所謂的 runNow()函數。愛掏網 - it200.com
在 preload 出現之前,你能做的很有限。愛掏網 - it200.com如果你的方法是在希望腳本執行的位置插入腳本,由于腳本只有在加載完成以后才能被瀏覽器執行,也就是說你得等上一會兒。愛掏網 - it200.com如果采用 XHR 提前加載腳本,瀏覽器會拒絕重用這段腳本,有些情況下,你可以使用 eval 函數來執行這段腳本,但該方法并不總是行得通,也不是完全沒有副作用。愛掏網 - it200.com
現在有了 preload,一切變得可能
var link = document.createElement("link");
link.;
link.rel = "preload";
link.as = "script";
document.head.appendChild(link);
上面這段代碼可以讓你預先加載腳本,下面這段代碼可以讓腳本執行
var script = document.createElement("script");
script.src = "http://www.webxq.com/vue/myscript.js";
document.body.appendChild(script);
- 基于標記語言的異步加載
先看代碼
preload 的 onload 事件可以在資源加載完成后修改 rel 屬性,從而實現非??岬漠惒劫Y源加載。愛掏網 - it200.com
腳本也可以采用這種方法實現異步加載
難道我們不是已經有了