溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何減少阻塞渲染的CSS

發(fā)布時間:2020-12-16 10:44:42 來源:億速云 閱讀:260 作者:小新 欄目:web開發(fā)

這篇文章給大家分享的是有關(guān)如何減少阻塞渲染的CSS的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。

“消除渲染阻止的JavaScript和CSS”。 這是我始終堅持使用的Google Page Speed Insights建議。Google建議您在頁面加載準(zhǔn)備就緒時將最初需要的CSS(內(nèi)插)CSS內(nèi)嵌并加載CSS的其余部分

當(dāng)訪問web頁面時,谷歌希望它只加載對初始視圖有用的內(nèi)容,并使用空閑時間來加載其他內(nèi)容。這樣,用戶可以盡早看到頁面。

如何減少阻塞渲染的CSS

我們可以做很多事情來最小化JavaScript的委托阻塞,比如代碼分割、樹抖動、緩存等等。

那么CSS呢?為此,我們可以通過隔離用于上述內(nèi)容的CSS(即關(guān)鍵的CSS)并首先加載它來最小化委托阻塞。然后我們可以加載非關(guān)鍵的CSS。

隔離關(guān)鍵的CSS是可以通過編程實現(xiàn)的,在本文中,我將向您展示如何將其委派給Webpack管道。

渲染阻止是什么意思?

如果資源是“渲染阻止”,則意味著瀏覽器在下載或處理該資源之前無法顯示該頁面。

通常情況下,我們會通過鏈接到文檔頭部的樣式表來以一種阻塞的方式加載CSS,如下所示:

<head>
  <link rel="stylesheet" href="/style.css">
  ...
</head>
<body>
  <p>I can't be seen until style.css has been loaded!</p>
</body>

當(dāng)web瀏覽器加載這個頁面時,它將從頭到尾地讀取它。當(dāng)瀏覽器到達鏈接標(biāo)記時,它將立即開始下載樣式表,并且在完成之前不會呈現(xiàn)頁面。

對于大型站點,特別是具有Bootstrap這樣的大框架的站點,樣式表可能是幾百kb,用戶必須耐心等待,直到完全下載完畢。

那么,我們是否應(yīng)該鏈接到主體中的樣式表,在那里呈現(xiàn)不會被阻塞?你可以這么做,但問題是,阻止租客并不完全是壞事,我們實際上想利用它。如果頁面渲染沒有任何CSS加載,我們會得到丑陋的“flash無風(fēng)格的內(nèi)容”:

如何減少阻塞渲染的CSS

我們想要的最佳點是在哪里渲染,用關(guān)鍵的css阻塞頁面,這是設(shè)計主視圖樣式所必需的,但是所有非關(guān)鍵的css都是在初始渲染之后加載的。

關(guān)鍵的CSS

看看我用Bootstrap和Webpack構(gòu)建的這個簡單頁面。這是它第一次渲染后的樣子:

如何減少阻塞渲染的CSS

該頁面還有一個模式,可通過“立即注冊”按鈕打開。 打開后,它看起來像這樣:

如何減少阻塞渲染的CSS

對于頁面的第一次呈現(xiàn),我們需要nav bar、jumbotron、button和其他一些布局和字體的一般規(guī)則的css規(guī)則。但我們不需要模態(tài)的規(guī)則,因為它不會立即顯示。考慮到這一點,我們可以將關(guān)鍵css與非關(guān)鍵css分離:

critical.css

.nav {
  ...
}

.jumbtron {
  ...
}

.btn {
  ...
}

non_critical.css

.modal {
  ...
}

如果你認(rèn)同這個概念,你可能會對以下兩個問題感興趣:

  • 我們?nèi)绾瓮ㄟ^編程來區(qū)分關(guān)鍵的和非關(guān)鍵的CSS ?

  • 如何讓頁面在第一次渲染前加載關(guān)鍵的CSS,在第一次渲染后加載非關(guān)鍵的CSS ?

示例項目

我將簡要地向您介紹這個項目的基本設(shè)置,以便在我們找到解決方案時能夠很快地消化。

首先,我加載引導(dǎo)SASS到我的輸入文件。

main.js

require("bootstrap-sass/assets/stylesheets/_bootstrap.scss");

我正在使用sass-loader處理此問題,并將其與Extract Text Plugin結(jié)合使用,以便將已編譯的CSS放入其自己的文件中。

我還使用HTML Webpack插件在構(gòu)建中創(chuàng)建HTML文件。 如您將很快看到的,該解決方案是必不可少的。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'sass-loader']
        })
      },
      ...
    ]
  },
  ...
  plugins: [
    new ExtractTextPlugin({ filename: 'style.css' }),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    })
  ] 
};

運行構(gòu)建后,HTML文件是這樣的。注意CSS是在頭部加載的,因此會阻塞渲染。

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vuestrap-code-split</title>
    <link href="/style.css" rel="stylesheet">
</head>
<body>
  <!--App content goes here, omitted for brevity.-->
  <script type="text/javascript" src="/build_main.js"></script>
</body>
</html>

以編程方式識別關(guān)鍵css

手動識別關(guān)鍵CSS會很麻煩。 要以編程方式做到這一點,我們可以使用Addy Osmani恰當(dāng)?shù)孛麨镃ritical的工具。 這是一個Node.js模塊,它將讀取HTML文檔,并標(biāo)識關(guān)鍵的CSS。 除此之外,它的作用還不止于此,我們很快就會看到。

Critical識別關(guān)鍵CSS的方法是使用PhantomJS加載頁面,使用指定的屏幕維度,并提取呈現(xiàn)頁面中使用的任何CSS規(guī)則。

以下是我們?nèi)绾螢檫@個項目設(shè)置:

const critical = require("critical");

critical.generate({
  
  /* The path of the Webpack bundle */
  base: path.join(path.resolve(__dirname), 'dist/'),
  src: 'index.html',
  dest: 'index.html',
  inline: true,
  extract: true,

  /* iPhone 6 dimensions, use whatever you like*/
  width: 375,
  height: 565,
  
  /* Ensure that bundled JS file is called */
  penthouse: {
    blockJSRequests: false,
  }
});

執(zhí)行時,這將把Webpack包輸出中的HTML文件更新為:

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Bootstrap Critical</title>
  <style type="text/css">
    /* Critical CSS is inlined into the document head, abbreviated here. */
    body {
      font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
      font-size: 14px;
      line-height: 1.42857;
      color: #333;
      background-color: #fff;
    }
    ...
  </style>
  <link href="/style.96106fab.css" rel="preload" as="style" onload="this.rel='stylesheet'">
  <noscript>
      <link href="/style.96106fab.css" rel="stylesheet">
  </noscript>
  <script>
    /*A script for loading the non-critical CSS goes here, omitted for brevity.*/
  </script>
</head>
<body>
  <!--App content goes here, omitted for brevity.-->
  <script type="text/javascript" src="/build_main.js"></script>
</body>
</html>

它還將輸出一個新的css文件,例如style.96106fab.css(文件名會自動添加一個散列)。這個css文件與原始樣式表相同,只是去掉了關(guān)鍵的css。

內(nèi)聯(lián)關(guān)鍵css

您將注意到關(guān)鍵的CSS已內(nèi)聯(lián)到文檔的頭部。這是最優(yōu)的,因為頁面不必從服務(wù)器加載它。

預(yù)加載非關(guān)鍵CSS

您還將注意到,非關(guān)鍵CSS加載了外觀精美的鏈接。 preload值告訴瀏覽器開始獲取非關(guān)鍵CSS供掛起使用。 但至關(guān)重要的是,預(yù)加載不是渲染阻止,因此無論預(yù)加載資源是否完成,瀏覽器都將繼續(xù)繪制頁面。

鏈接中的onload屬性允許我們在非關(guān)鍵的CSS最終加載后運行腳本。關(guān)鍵模塊自動將腳本內(nèi)聯(lián)到文檔中,從而提供跨瀏覽器兼容的方式將非關(guān)鍵樣式表加載到頁面中。

<link href="/style.96106fab.css" rel="preload" as="style" onload="this.rel='stylesheet'">

將critical放入webpack管道

我制作了一個名為html關(guān)鍵webpack plugin的webpack插件,它僅僅是關(guān)鍵模塊的包裝器。它將在您的文件從HTML網(wǎng)頁包插件發(fā)出后運行。

以下是如何將它包含在Webpack項目中:

const HtmlCriticalPlugin = require("html-critical-webpack-plugin");

module.export = {
  ...
  plugins: [
    new HtmlWebpackPlugin({ ... }),
    new ExtractTextPlugin({ ... }),
    new HtmlCriticalPlugin({
      base: path.join(path.resolve(__dirname), 'dist/'),
      src: 'index.html',
      dest: 'index.html',
      inline: true,
      minify: true,
      extract: true,
      width: 375,
      height: 565,
      penthouse: {
        blockJSRequests: false,
      }
    })
  ] 
};

注意:您可能只應(yīng)該在生產(chǎn)構(gòu)建中使用它,而不是在開發(fā)中,因為它會使您的構(gòu)建非常慢!

性能結(jié)果

現(xiàn)在我已經(jīng)隔離了關(guān)鍵的CSS,并在空閑時間加載了非關(guān)鍵的CSS,那么如何改進性能呢?

我使用Chrome的燈塔擴展來尋找答案。請記住,我們試圖優(yōu)化的度量標(biāo)準(zhǔn)是第一次有意義的繪制的時間,它基本上告訴我們用戶看到某些東西需要多長時間。

在實施關(guān)鍵的CSS:

如何減少阻塞渲染的CSS

關(guān)鍵的CSS實現(xiàn)后:

如何減少阻塞渲染的CSS

如您所見,我的應(yīng)用程序在整整一秒鐘前就獲得了一幅有意義的畫作,并且在半秒鐘前就實現(xiàn)了交互。

實際上,你可能不會在你的應(yīng)用程序中得到如此顯著的改進,因為我的css已經(jīng)完全膨脹了(我包括了整個引導(dǎo)庫),在這樣一個簡單的應(yīng)用程序中,我沒有很多關(guān)鍵的css規(guī)則。

感謝各位的閱讀!關(guān)于如何減少阻塞渲染的CSS就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

css
AI