如何以及為什麼應該內聯關鍵 CSS

在互聯網早期年代,網站主要是用來顯示基於文本的信息。慢慢地,連接速度提升了,用戶已經能相當快地下載高分辨率的圖像和視頻了。更多IT技術乾貨,歡迎大家去微信鎖定"朗妹兒"的這個公眾號,每天都有新的乾貨更新。現在網站就不僅僅是以文本的形式提供所需信息了。網站正變得越來越複雜,帶有 CSS 和 JavaScript 框架,以及大量的插件等等,加載這些東西所需的所有文件要花一些時間。

更快的網站可以帶來更佳的用戶體驗,這在網站成功中可以產生巨大的差異。那麼要開始提升性能,開發者能做哪些事情呢?其中之一是將關鍵 CSS 內聯,同時異步加載非關鍵 CSS。本文將一個一個學習這些知識點,以幫助你提升網站的性能。

什麼是關鍵(Critical) CSS?

項目中的關鍵 CSS 是用來格式化網站首屏(above-the-fold)內容的 CSS。首屏內容是用戶在你的網站上最先看到的內容,可以包括導航欄和其它元素。所以,儘可能快地格式化和渲染網站的這部分是很重要的。

這裡我想指出的一件事情是,網站訪問者可能使用五花八門的帶有不同視口的設備訪問你的網站。所以,首屏內容本身是搞不定的。要解決這個問題,你還應該把與基礎佈局和排版相關的所有 CSS 也看作是關鍵的。

現代 Web 開發實踐通常會推薦你內聯關鍵 CSS。像下面這樣,把關鍵 CSS 放在網頁中:

1.

2.

3.

4.

一個優化了的網頁

5.

6.

7.

8. (你的HTML標記)

9.

10.

為什麼內聯是必須的?

如果你導航到 ,分析你的網頁之一,你可能會看到警告你要通過內聯關鍵 CSS,並且異步加載阻塞渲染的樣式,來優化你交付的 CSS。

瀏覽器只有在加載完成所有 CSS 文件後,才會渲染網頁的首屏內容。如果有很多文件需要加載,這就是個大事。

並非所有用戶有快速互聯網連接,如果在他們可以看到他們衝著來訪問的實際內容之前, 還要等待庫、CSS 和 JavaScript 下載,這可能是很令人失望的。即使是有快速連接的用戶,在某些情況下,也會喪失連接,比如通過隧道時。此時,如果你的網站有內聯的關鍵 CSS,而且在顯示主要內容之前不加載其它文件的話,用戶依然可以訪問主要內容。

如下的圖像闡述了普通網頁和優化了的網頁的差別。正如你所見,優化了的版本會讓用戶早 0.5 秒訪問到內容。在有很多額外的庫需要加載時,這種提升會更明顯。

如何以及為什麼應該內聯關鍵 CSS

你應該內聯關鍵 CSS 嗎?

得視情況而定。如果沒有用很重的框架或者庫,並且你自己的 CSS 文件也夠小,那麼就不需要內聯 CSS。

如果你用了像 BootStrap 這樣的框架,可能你用不到該框架提供的所有功能。在這種情況下,你可以只從框架的樣式表中提取關鍵 CSS,然後異步加載實際的框架。這樣也能顯著地提升網站的速度。

在內聯時,樣式表可以被緩存。HTML 通常是不被緩存的(這樣做也不是個好主意!)。這意味著二者之間偶然會有區別。在更新時要記住這點!此外,內聯的 CSS 會導致每次用戶加載網站時網頁會大一點。比如,如果網站中每個頁面有 30 KB 的內聯 CSS,那麼一個用戶訪問 10 個頁面就會消耗掉用戶 300KB。這聽起來好像也不是什麼大事,但是在世界的某些地方數據是昂貴的,還有人用的是 3G/4G 數據套餐。要確保你打算規劃為內聯的 CSS 對你的網頁是真正至關重要的,並且。

找到關鍵 CSS

手動查找關鍵 CSS 是一件無聊而艱鉅的任務。幸運的是,有工具可以幫助我們快速找到。

使用 Grunt

如果你熟悉 構建系統,有一個插件 可以讓這個過程變得更簡單點。如果你喜歡用 Gulp 或者 npm,下一節我們會講如何用這兩個工具執行此過程。

首先,需要用如下命令安裝該插件:

1. npm install grunt-critical --save-dev

還需要創建 Gruntfile.js。這個文件包含設置插件的各種選項的所有代碼,包括視口大小、源文件和目標文件的路徑。這裡有一個示例:

1. module.exports = function(grunt) {

2.

3. grunt.initConfig({

4. critical: {

5. extract: {

6. options: {

7. base: './',

8. width: 1024,

9. height: 768,

10. minify: true

11. },

12. src: 'path/to/initial.html',

13. dest: 'path/to/final.html'

14. }

15. }

16. });

17.

18. grunt.loadNpmTasks('grunt-critical');

19. grunt.registerTask('default', ['critical']);

20.

21. };

在封裝的函數中,我們使用 grunt.initConfig 方法指定所有的配置選項。在本例中,我已經指定了一個 base 目錄,源文件和目標文件要寫到這個目錄中。我也將 minify 選項設置為 true,這樣我得到的就是一個插件抽取的關鍵 CSS 的最終壓縮版本。src 屬性包含了源文件的位置,這個文件要被再次操作。dest 屬性包含了最終輸出要保存的位置。

如果 dest 文件是一個樣式表,最終的 CSS 被保存到一個文件,供將來使用。但是,如果 dest 屬性是一個標記文件(HTML、PHP 等等),那麼該 CSS 就被內聯,已有的樣式表被封裝進一個 JavaScript 函數中,用於異步加載。對於 disabled 掉 JavaScript 的用戶,還會會添加一個 noscript 塊。還有其它的選項,你可以訪問 來看看全部選項列表。

現在,在控制檯鍵入 grunt 就可以運行該插件了:

1. C:\path\to\project>grunt

如果初始文件有如下標記:

1.

2.

3.

4.

The Optimizer

5.

6.

7.

8.

All the markup stuff

9.

10.

現在它就會變成如下這樣:

1.

2.

3.

4.

The Optimizer

5.

6.

7. JavaScript to load styles asynchronously...

8.

9.

12.

13.

14.

All the markup stuff

15.

16.

正如你所見,這個插件會為你做完所有工作。現在,如果用 PageSpeed 分析你的頁面,會得到更好的分數。在我的例子中,分數從 86 變為 95。

有很多其它 Grunt 插件可以實現相同的效果,比如 和 。但是,在使用這些插件時,必須指定從哪個樣式表抽取關鍵 CSS。

使用 npm 模塊

是由 Addy Osmani 創建的 npm 包,它包含 grunt-critical 插件使用的功能。這個包你可以不與 Grunt 一起用,直接使用 JavaScript 和 npm,用它從一個網頁中抽取和內聯關鍵路徑或者首屏CSS。要安裝這個包,你需要運行:

1. npm install critical --save-dev

安裝完包後,需要在項目目錄中創建一個 JavaScript 文件,然後把如下代碼放進去:

1. var critical = require('critical');

2.

3. critical.generate({

4. inline: true,

5. base: 'initial/',

6. src: 'homepage.html',

7. dest: 'final/homepage.html',

8. width: 1366,

9. height: 768

10. });

可以指定一堆選項來創建優化的網頁。設置 inline 為 true,會生成內聯 CSS 的 HTML 頁面,否則就生成一個 CSS 文件。width 和 height選項用來設置目標視口的大小。在可以找到很多其它選項,比如壓縮內聯 CSS。優化了的網頁與 Grunt 插件的輸出看起來會差不多。

可以使用的另一個 npm 模塊是 模塊。該模塊從提供的 URL 中生成關鍵 CSS。生成的 CSS 可以用一個回調函數進一步處理,因為 Grunt 插件就是基於這個包的。

使用 Gulp

如果你覺得用 Gulp 更舒服,Addy Osmanni 推薦 Gulp 用戶直接使用 Critical npm 模塊。Addy Osmani 在 Critical GitHub page 上為 Gulp 用戶提供的示例看起來像這樣:

1. var critical = require('critical').stream;

2.

3. // Generate & Inline Critical-path CSS

4. gulp.task('critical', function () {

5. return gulp.src('dist/*.html')

6. .pipe(critical({base: 'dist/', inline: true, css: ['dist/styles/components.css','dist/styles/main.css']}))

7. .pipe(gulp.dest('dist'));

8. });

javascript

Critical 團隊還有。

還有一個 插件可以生成關鍵 CSS。但是,這個插件是抽取從 CSS 中抽取某些選擇器類型,而不是檢測首屏元素等等。

更多資源

另一個工具是 Jonas Ohlsson 的 。用這個工具,你只需要鍵入網頁 URL,然後提供你要抽取關鍵 CSS 的所有 CSS。點擊 "Create Critical Path CSS" 按鈕,此後就會輸出你要的 CSS。

總結

應該還是不應該使用內聯關鍵 CSS,取決於用戶的訪問模式,以及網站的結構。如果你的網站頁面不多,用戶訪問也不頻繁,或者你已經有一個帶有框架和插件的複雜網站,那麼內聯關鍵 CSS 可以顯著提升性能。

對於內聯,唯一不爽的是它會對每次訪問加大了頁面的重量。但是有辦法可以緩解一下,比如使用 cookies 以及在第一次訪問時只發送關鍵 CSS,同時依然異步加載全部 CSS 文件,然後緩存該文件。這樣做有點複雜,但是可以得到兩全其美的效果。

你已經嘗試在自己的項目中內聯 CSS 了嗎?性能提升明顯不?你對同行有其它建議沒有?請在評論中讓我們知道。


分享到:


相關文章: