首頁  >  文章  >  web前端  >  詳解減少阻塞渲染的CSS的自動化的方法

詳解減少阻塞渲染的CSS的自動化的方法

青灯夜游
青灯夜游轉載
2020-12-15 09:39:471714瀏覽

詳解減少阻塞渲染的CSS的自動化的方法

「消除渲染阻止的JavaScript和CSS」。這是我始終堅持使用的Google Page Speed Insights建議。 Google建議您在頁面加載準備好時將最初需要的CSS(內插)CSS內嵌並加載CSS的其餘部分

當訪問web頁面時,谷歌希望它只加載對初始視圖有用的內容,並使用空閒時間來載入其他內容。這樣,使用者可以儘早看到頁面。

詳解減少阻塞渲染的CSS的自動化的方法

我們可以做很多事情來最小化JavaScript的委託阻斷,例如程式碼分割、樹抖動、快取等等。

那麼CSS呢?為此,我們可以透過隔離用於上述內容的CSS(即關鍵的CSS)並首先載入它來最小化委託阻塞。然後我們可以載入非關鍵的CSS。

隔離關鍵的CSS是可以透過程式設計來實現的,在本文中,我將向您展示如何將其委派給Webpack管道。

渲染阻止是什麼意思?

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

通常情況下,我們會透過連結到文件頭的樣式表來以一種阻塞的方式載入CSS,如下所示:

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

當web瀏覽器載入這個頁面時,它將從頭到尾讀取它。當瀏覽器到達連結標記時,它將立即開始下載樣式表,並且在完成之前不會呈現頁面。

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

那麼,我們是否應該連結到主體中的樣式表,在那裡呈現不會被阻塞?你可以這麼做,但問題是,阻止租客並不完全是壞事,我們實際上想利用它。如果頁面渲染沒有任何CSS加載,我們會得到醜陋的“flash無風格的內容”:

詳解減少阻塞渲染的CSS的自動化的方法

我們想要的最佳點是在哪裡渲染,用關鍵的css阻塞頁面,這是設計主視圖樣式所必需的,但是所有非關鍵的css都是在初始渲染之後載入的。

關鍵的CSS

看看我用Bootstrap和Webpack建立的這個簡單頁面。這是它第一次渲染後的樣子:

詳解減少阻塞渲染的CSS的自動化的方法

該頁面還有一個模式,可透過「立即註冊」按鈕開啟。打開後,它看起來像這樣:

詳解減少阻塞渲染的CSS的自動化的方法

對於頁面的第一次呈現,我們需要nav bar、jumbotron、button和其他一些佈局和字體的一般規則的css規則。但我們不需要模態的規則,因為它不會立即顯示。考慮到這一點,我們可以將關鍵css與非關鍵css分開:

critical.css

.nav {
  ...
}

.jumbtron {
  ...
}

.btn {
  ...
}

non_critical.css

.modal {
  ...
}

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

  • 我們如何透過程式設計來區分關鍵的和非關鍵的CSS ?

  • 如何讓頁面在第一次渲染前載入關鍵的CSS,在第一次渲染後載入非關鍵的CSS ?

範例專案

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

首先,我載入引導SASS到我的輸入檔。

main.js

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

我正在使用sass-loader處理此問題,並將其與Extract Text Plugin結合使用,以便將已編譯的CSS放入自己的檔案中。

我還使用HTML Webpack插件在建置中建立HTML檔案。如您將很快看到的,該解決方案是必不可少的。

webpack.config.js

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

執行建置後,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>

以程式識別關鍵css

手動辨識關鍵CSS會很麻煩。要以程式方式做到這一點,我們可以使用Addy Osmani恰當地命名為Critical的工具。這是一個Node.js模組,它將讀取HTML文檔,並識別關鍵的CSS。除此之外,它的作用不止於此,我們很快就會看到。

Critical識別關鍵CSS的方法是使用PhantomJS載入頁面,使用指定的螢幕維度,並提取呈現頁面中使用的任何CSS規則。

以下是我們如何為這個專案設定:

const critical = require("critical");

critical.generate({
  
  /* The path of the Webpack bundle */
  base: path.join(path.resolve(__dirname), &#39;dist/&#39;),
  src: &#39;index.html&#39;,
  dest: &#39;index.html&#39;,
  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,
  }
});

执行时,这将把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=&#39;stylesheet&#39;">
  <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文件与原始样式表相同,只是去掉了关键的css。

内联关键css

您将注意到关键的CSS已内联到文档的头部。这是最优的,因为页面不必从服务器加载它。

预加载非关键CSS

您还将注意到,非关键CSS加载了外观精美的链接。 preload值告诉浏览器开始获取非关键CSS供挂起使用。 但至关重要的是,预加载不是渲染阻止,因此无论预加载资源是否完成,浏览器都将继续绘制页面。

链接中的onload属性允许我们在非关键的CSS最终加载后运行脚本。关键模块自动将脚本内联到文档中,从而提供跨浏览器兼容的方式将非关键样式表加载到页面中。

<link href="/style.96106fab.css" rel="preload" as="style" onload="this.rel=&#39;stylesheet&#39;">

将critical放入webpack管道

我制作了一个名为html关键webpack plugin的webpack插件,它仅仅是关键模块的包装器。它将在您的文件从HTML网页包插件发出后运行。

以下是如何将它包含在Webpack项目中:

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

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

注意:您可能只应该在生产构建中使用它,而不是在开发中,因为它会使您的构建非常慢!

性能结果

现在我已经隔离了关键的CSS,并在空闲时间加载了非关键的CSS,那么如何改进性能呢?

我使用Chrome的灯塔扩展来寻找答案。请记住,我们试图优化的度量标准是第一次有意义的绘制的时间,它基本上告诉我们用户看到某些东西需要多长时间。

在实施关键的CSS:

詳解減少阻塞渲染的CSS的自動化的方法

关键的CSS实现后:

詳解減少阻塞渲染的CSS的自動化的方法

如您所见,我的应用程序在整整一秒钟前就获得了一幅有意义的画作,并且在半秒钟前就实现了交互。

实际上,你可能不会在你的应用程序中得到如此显著的改进,因为我的css已经完全膨胀了(我包括了整个引导库),在这样一个简单的应用程序中,我没有很多关键的css规则。

英文原文地址:https://vuejsdevelopers.com/2017/07/24/critical-css-webpack/

更多编程相关知识,请访问:编程课程!!

以上是詳解減少阻塞渲染的CSS的自動化的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:vuejsdevelopers.com。如有侵權,請聯絡admin@php.cn刪除