【第781期】理解Critical CSS
前言
前段時間在微博上看到 inline 首屏 css,一臉懵逼,這又是什麼新科技。 本著好奇的心搜索看看,最後@大漠給我推薦了這篇。
正文從這開始~
CSS 資源的載入情況對瀏覽器渲染頁面的影響很大,這是因為默認情況下瀏覽器只有在完成 部分 CSS 樣式的載入、解析之後才會渲染頁面。這種渲染方式意味著,如果 CSS 文件很大,那麼用戶就必須等待很長的時間才能看到渲染結果。針對這一問題,我們將在接下來的內容中討論一種非常規的解決方案,提高頁面的渲染速度,這一方案常被稱為 critical rendering path。
我們要做的優化就是找出渲染首屏的最小 CSS 集合(Critical CSS),並把它們寫到 部分,從而讓瀏覽器接收到 HTML 文件後就儘快渲染出頁面。對於剩餘部分的 CSS,我們可以使用非同步的方式進行載入。對於如何判斷哪些 CSS 是首屏渲染需要的,我們需要通過分析 DOM 結構來確定,當然,手動來處理這些工作就太單調乏味了,所以在後文我會為大家介紹幾種自動化處理的工具。
實戰
首先,我們再重新梳理一遍步驟:將樣式分成兩份,一份是渲染首屏的最小集合,另一份是渲染頁面剩餘部分的樣式,對於第一份,將其內嵌在 部分,對於第二部分則使用非同步的方式載入。這種解決方案初看起來有些怪異,但實質上很簡單,通過一次請求就獲取到 HTML 文檔和渲染首屏的 CSS 樣式,儘快地為用戶提供響應結果。為了更好地理解這一方案,下面的代碼演示了核心的 HTML 結構:
/* inlined critical CSS */
loadCSS( non-critical.css );
...body goes here
在上面的代碼中,我們取出首屏渲染所必須的 critical CSS,以內聯的方式寫在 之中,然後使用 loadCSS() 非同步載入剩餘部分的 CSS 樣式,這相當於離線載入剩餘部分的 CSS 樣式,然後在後台將其注入到頁面中。
看完結構我們說說問題,首先就是這看起來很難以維護,對於這個問題,我想說何必手工處理這兩部分的樣式呢,讓自動化工具來幫你自動處理吧,比如說下文中演示的 Critical,它是一個 Node.js 的第三方庫,幫助開發者自動篩選 critical CSS。
接下來我們就使用 Grunt 搭配 Critical 自動化處理 CSS,如果你還沒有安裝過 Grunt,可以使用以下命令在全局安裝 Grunt:
npm install-g grunt-cli
接下來,安裝 Grunt 任務執行器:
npm install grunt--save-dev
安裝 grunt-critical 插件:
npm install grunt-critical--save-dev
然後,為 Grunt 創建配置文件,如下所示:
module.exports=function(grunt){
grunt.initConfig({
critical:{
dist:{
options:{
base: ./
},
// The source file
src: page.html ,
// The destination file
dest: result.html
}
}
});
// Load the plugins
grunt.loadNpmTasks( grunt-critical );
// Default tasks.
grunt.registerTask( default ,[ critical ]);
};
在上面的配置文件中,我們對 Critical 進行了配置,讓其檢查 page.html 文件的 CSS 樣式,並計算出該頁面的 Critical CSS,分析結束後它會將 Critical CSS 內聯到該頁面。
通過在終端輸入 grunt 運行該插件:
GIF/23K
執行完成上述命令之後進入相關的文件夾,你會發現文件夾中多出了一個 result.html 文件,該文件包含了一個內聯的 CSS,並使用非同步的方式載入剩餘的 CSS。
實際上該插件使用無界面的 Webkit 瀏覽器 PhantomJS 截取 Critical CSS。這也就是說,它會自動地載入指定頁面並測試最佳的 Critical CSS。如果你想對該功能做更細緻的配置,比如說配置不同的屏幕尺寸,那麼可以仿照下面的配置文件進行修改:
critical:{
dist:{
options:{
base: ./ ,
dimensions:[{
width:1300,
height:900
},
{
width:500,
height:900
}]
},
files:[
{src:[ index.html ],dest: dist/index.html }
]
}
}
通過上面的配置,Critical 插件將會為頁面生成多尺寸的內聯 Critical CSS,讓使用不同設備的用戶擁有相同的體驗效果。如我們所知,3G 或 4G 等移動信號是不穩定的,這也是我們使用這一解決方案的初衷以及其重要性的體現。
線上環境
使用 Critical 等工具是一個自動化實現 Critical CSS 的好方案,但是它是否適應真實的開發環境呢?毫無問題,就像你之前的部署一樣方便,唯一需要牢記的就是每次構建或修改 CSS 之後都要執行 Grunt 來處理 Critical CSS。
上面的 Grunt 配置已經可以很好地處理單個文件了,如果要處理多個文件或者整個文件夾,那麼需要將 Grunt 的配置文件更新為如下形式:
critical:{
dist:{
options:{
base: ./ ,
dimensions:[{
width:1300,
height:900
},
{
width:500,
height:900
}]
},
files:[
{src:[ index.html ],dest: dist/index.html },
{src:[ blog.html ],dest: dist/blog.html }
{src:[ about.html ],dest: dist/about.html }
{src:[ contact.html ],dest: dist/contact.html }
]
}
}
或者使用下面的配置方法處理整個目錄下的文件:
critical:{
dist:{
options:{
base: ./ ,
dimensions:[{
width:1300,
height:900
},
{
width:500,
height:900
}],
src: *.html ,
dest: dist/
}
}
}
測試
如果想測試使用 Critical 前後的性能改變,推薦你使用免費的在線工具 Google Pagespeed Insights,只需輸入指定頁面的鏈接即可。該工具會自動載入頁面,你會發現頁面的渲染阻塞時間變少了,非常棒。另一個非常好用的工具是 WebPagetest。
WebPagetest 是一個免費的工具,用於幫助開發者在全球各地測試網站速度,測試完成會提供一個詳細的測試結果信息。如果選擇使用 Visual Comparison,則可以添加多個鏈接地址進行比較,便於比較使用 Critical CSS 前後的性能表現。
使用 Critical CSS 的根本原因就是儘快為用戶呈現頁面,使用 speed index 就可以對頁面內容的呈現時間進行測試,它也是由 WebPagetest 提供的功能。SpeedIndex 會測量頁面渲染的整個流程,最終計算出一個分數值量化頁面渲染的速度。如果你已經完成了上面使用 Grunt 拆分 Critical CSS 的操作,那麼現在就可以使用 SpeedIndex 進行測試了,結果可能會嚇你一跳哈。
深入淺出
對於大多數的性能優化技巧都存在其優點和缺陷,Critical CSS 的弊端在於內聯樣式是無法被瀏覽器緩存的。對於動態變化的頁面,HTML 通常是不做緩存處理的,這也就是說內聯在 HTML 中的 Critical CSS 會被反覆下載。對於使用內聯樣式的爭論已經很多了,我建議你閱讀 Hans Christian Reinl 的文章 《A counter statement: Putting the CSS in the head》。如果你在使用 CDN,那麼建議你使用 CDN 緩存頁面的 non-Critical CSS,減少資源的響應時間,避免直接向原始伺服器獲取資源。
使用內聯 CSS 的方案也可以很好地兼容傳統的網頁,但是否適用還要取決於你的使用場景,比如是否是用 JavaScript 生成 HTML 的頁面,是否是單頁應用。理解 Critical CSS 的工作機制和適用條件非常重要,我非常喜歡 Guy Podjarny 的這句話:
雖然有種種限制,但是內聯樣式仍是前端性能優化的重要方式,因此,你可以用它,但也需要慎重,以免誤用。
在 《Why Inlining Everything Is NOT The Answer》 一文中,他就使用內聯樣式的時機做了更詳細的分析。
瑕疵
因為這裡面使用到了多個工具,而且對 Critical CSS 的計算也在改善之中,所以如果你遇到了 Bug,請在 GitHub 項目主頁上提交 issue 或 pull request。優化網站的 Critical Rendering Path 是一個長遠的過程,使用本文所介紹的優化方案可以讓頁面是一個響應式的,也不會對頁面設計提出額外的要求。
更多資料
如果你喜歡使用 Gulp,那麼可以參考文章 《how to optimize a basic page with Gulp》。此外,用於篩選 Critical CSS 的插件還有 Penthouse 和 criticalCSS。在這裡也建議你閱讀 Filamen Group 的文章 《How we make RWD sites load fast as heck》,看一看他們是怎麼使用本文的方案提高頁面載入速度的。
Smashing Magazine 的主編 Vitaly Friedman 寫過一篇有關 Smashing Magazine 使用該方案優化頁面性能的文檔,如果你喜歡獲取更多有關 Critical Rendering Path 的文章,可以觀看 Udacity 網站的免費課程。Google 開發者網站 也有很多優化 CSS 載入的文章,非常值得一看。Patrick Hamman 也寫了很多優秀的文章 how to identify critical CSS,演示如何優化網站性能。
※六位國內外前端技術專家,帶你玩轉前端最熱門技術
※在Vue.js中使用Mixins
※晉陞評審的套路
※螞蟻金服招聘高級前端開發工程師/前端開發專家
※正則表達式回溯法原理
TAG:前端早讀課 |
※首發 | DOMANI 東倉:AUTASON BLACK 新店設計!【環球設計1781期】
※DOMANI 東倉:AUTASON BLACK 新店設計!環球設計1781期
※蝴蝶781Anthem——簡單純粹的讚歌,懶人的絕佳選擇
※入門級電競顯示器 航嘉 M2781C促銷959元
※商贏環球:2017年凈利預增739%-781%
※2019年1-7月中國集成電路出口量為117810百萬個 同比下降7.7%
※No.781 許章潤 | 華人與狗,還是華人與狗
※華麗外表下的堅實內心 松下V-M781F指紋鎖評測
※西部4567810贏了東部94分!馬刺重返季後賽竟靠湖人?
※781億債務!AA+省屬國企營口港違約,債權人陣容相當豪華
※江淮又拿第一!唐駿歐鈴大漲781%!2月輕微卡市場銷量分析
※錦龍股份:上半年凈利7817萬元 同比扭虧為盈
※此國二戰造1131艘潛艇,781艘戰時被摧毀,潛艇兵損失慘重
※揭露45名侵華戰犯罪行!一將領殘害7812人,竟被釋放回國安享晚年
※最多屠殺7812人!45名日本侵華戰犯親筆供詞暴行讓人瞠目
※諾基亞王者歸來:銷量上漲781%,闖進前十名!
※空間突破!1781年英國天文學家如何在太陽系中發現新行星
※首日狂收1781萬票房,投資人樂壞了,網友:她真是票房靈藥!
※重磅!總建築面積59781平方米的「夢想城堡」,世界最大舞美基地即將啟用!
※科比的天賦不高,靠自己的努力走到今天,這句話正確嗎?關注者 781 被瀏覽