教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

CSS性能優(yōu)化的技巧(一)

更新時間:2018年09月13日16時19分 來源:傳智播客 瀏覽次數:

  下面我們開始介紹實踐型的4個優(yōu)化技巧,先從首屏關鍵CSS開始。

  1. 內聯首屏關鍵CSS(Critical CSS)

  性能優(yōu)化中有一個重要的指標——首次有效繪制(First Meaningful Paint,簡稱FMP)即指頁面的首要內容(primary content)出現在屏幕上的時間。這一指標影響用戶看到頁面前所需等待的時間,而**內聯首屏關鍵CSS(即Critical CSS,可以稱之為首屏關鍵CSS)**能減少這一時間。

  大家應該都習慣于通過link標簽引用外部CSS文件。但需要知道的是,將CSS直接內聯到HTML文檔中能使CSS更快速地下載。而使用外部CSS文件時,需要在HTML文檔下載完成后才知道所要引用的CSS文件,然后才下載它們。所以說,內聯CSS能夠使瀏覽器開始頁面渲染的時間提前,因為在HTML下載完成之后就能渲染了。

  既然內聯CSS能夠使頁面渲染的開始時間提前,那么是否可以內聯所有的CSS呢?答案顯然是否定的,這種方式并不適用于內聯較大的CSS文件。因為初始擁塞窗口3存在限制(TCP相關概念,通常是 14.6kB,壓縮后大小),如果內聯CSS后的文件超出了這一限制,系統(tǒng)就需要在服務器和瀏覽器之間進行更多次的往返,這樣并不能提前頁面渲染時間。因此,我們應當只將渲染首屏內容所需的關鍵CSS內聯到HTML中。

  既然已經知道內聯首屏關鍵CSS能夠優(yōu)化性能了,那下一步就是如何確定首屏關鍵CSS了。顯然,我們不需要手動確定哪些內容是首屏關鍵CSS。Github上有一個項目Critical CSS4,可以將屬于首屏的關鍵樣式提取出來,大家可以看一下該項目,結合自己的構建工具進行使用。當然為了保證正確,大家最好再親自確認下提取出的內容是否有缺失。

  不過內聯CSS有一個缺點,內聯之后的CSS不會進行緩存,每次都會重新下載。不過如上所說,如果我們將內聯后的文件大小控制在了14.6kb以內,這似乎并不是什么大問題。

  如上,我們已經介紹了為什么要內聯關鍵CSS以及如何內聯,那么剩下的CSS我們怎么處理好呢?建議使用外部CSS引入剩余CSS,這樣能夠啟用緩存,除此之外還可以異步加載它們。

  2. 異步加載CSSCSS會阻塞渲染,在CSS文件請求、下載、解析完成之前,瀏覽器將不會渲染任何已處理的內容。有時,這種阻塞是必須的,因為我們并不希望在所需的CSS加載之前,瀏覽器就開始渲染頁面。那么將首屏關鍵CSS內聯后,剩余的CSS內容的阻塞渲染就不是必需的了,可以使用外部CSS,并且異步加載。

  那么如何實現CSS的異步加載呢?有以下四種方式可以實現瀏覽器異步加載CSS。

  第一種方式是使用JavaScript動態(tài)創(chuàng)建樣式表link元素,并插入到DOM中。

  // 創(chuàng)建link標簽const myCSS = document.createElement( "link" );myCSS.rel = "stylesheet";myCSS.href = "mystyles.css";// 插入到header的最后位置document.head.insertBefore( myCSS, document.head.childNodes[ document.head.childNodes.length - 1 ].nextSibling );

  第二種方式是將link元素的media屬性設置為用戶瀏覽器不匹配的媒體類型(或媒體查詢),如media="print",甚至可以是完全不存在的類型media="noexist"。對瀏覽器來說,如果樣式表不適用于當前媒體類型,其優(yōu)先級會被放低,會在不阻塞頁面渲染的情況下再進行下載。

  當然,這么做只是為了實現CSS的異步加載,別忘了在文件加載完成之后,將media的值設為screen或all,從而讓瀏覽器開始解析CSS。

  復制代碼與第二種方式相似,我們還可以通過rel屬性將link元素標記為alternate可選樣式表,也能實現瀏覽器異步加載。同樣別忘了加載完成之后,將rel改回去。

  復制代碼上述的三種方法都較為古老?,F在,rel="preload"5這一Web標準指出了如何異步加載資源,包括CSS類資源。

  復制代碼注意,as是必須的。忽略as屬性,或者錯誤的as屬性會使preload等同于XHR請求,瀏覽器不知道加載的是什么內容,因此此類資源加載優(yōu)先級會非常低。as的可選值可以參考上述標準文檔。

  看起來,rel="preload"的用法和上面兩種沒什么區(qū)別,都是通過更改某些屬性,使得瀏覽器異步加載CSS文件但不解析,直到加載完成并將修改還原,然后開始解析。

  但是它們之間其實有一個很重要的不同點,那就是使用preload,比使用不匹配的media方法能夠更早地開始加載CSS。所以盡管這一標準的支持度還不完善,仍建議優(yōu)先使用該方法。

  該標準現在已經是候選標準,相信瀏覽器會逐漸支持該標準。在各瀏覽器的支持度如下圖所示。


  

  從上圖可以看出這一方法在現在的瀏覽器中支持度不算樂觀,不過我們可以通過loadCSS進行polyfill,所以支持不支持,這都不是事兒。

  3. 文件壓縮性能優(yōu)化時有一個最容易想到,也最常使用的方法,那就是文件壓縮,這一方案往往效果顯著。

  文件的大小會直接影響瀏覽器的加載速度,這一點在網絡較差時表現地尤為明顯。相信大家都早已習慣對CSS進行壓縮,現在的構建工具,如webpack、gulp/grunt、rollup等也都支持CSS壓縮功能。壓縮后的文件能夠明顯減小,可以大大降低了瀏覽器的加載時間。

  4. 去除無用CSS雖然文件壓縮能夠降低文件大小。但CSS文件壓縮通常只會去除無用的空格,這樣就限制了CSS文件的壓縮比例。那是否還有其他手段來精簡CSS呢?答案顯然是肯定的,如果壓縮后的文件仍然超出了預期的大小,我們可以試著找到并刪除代碼中無用的CSS。

  一般情況下,會存在這兩種無用的CSS代碼:一種是不同元素或者其他情況下的重復代碼,一種是整個頁面內沒有生效的CSS代碼。對于前者,在編寫的代碼時候,我們應該盡可能地提取公共類,減少重復。對于后者,在不同開發(fā)者進行代碼維護的過程中,總會產生不再使用的CSS的代碼,當然一個人編寫時也有可能出現這一問題。而這些無用的CSS代碼不僅會增加瀏覽器的下載量,還會增加瀏覽器的解析時間,這對性能來說是很大的消耗。所以我們需要找到并去除這些無用代碼。

  當然,如果手動刪除這些無用CSS是很低效的。我們可以借助Uncss庫來進行。Uncss可以用來移除樣式表中的無用CSS,并且支持多文件和JavaScript注入的CSS。



作者:傳智播客前端與移動開發(fā)培訓學院

首發(fā):http://web.itcast.cn

0 分享到:
和我們在線交談!