0

0

详解减少阻塞渲染的CSS的自动化的方法

青灯夜游

青灯夜游

发布时间:2020-12-15 09:39:47

|

1969人浏览过

|

来源于vuejsdevelopers

转载

详解减少阻塞渲染的CSS的自动化的方法

“消除渲染阻止的JavaScript和CSS”。 这是我始终坚持使用的Google Page Speed Insights建议。Google建议您在页面加载准备就绪时将最初需要的CSS(内插)CSS内嵌并加载CSS的其余部分

当访问web页面时,谷歌希望它只加载对初始视图有用的内容,并使用空闲时间来加载其他内容。这样,用户可以尽早看到页面。

1.jpg

我们可以做很多事情来最小化JavaScript的委托阻塞,比如代码分割、树抖动、缓存等等。

立即学习前端免费学习笔记(深入)”;

那么CSS呢?为此,我们可以通过隔离用于上述内容的CSS(即关键的CSS)并首先加载它来最小化委托阻塞。然后我们可以加载非关键的CSS。

隔离关键的CSS是可以通过编程实现的,在本文中,我将向您展示如何将其委派给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>

当web浏览器加载这个页面时,它将从头到尾地读取它。当浏览器到达链接标记时,它将立即开始下载样式表,并且在完成之前不会呈现页面。

对于大型站点,特别是具有Bootstrap这样的大框架的站点,样式表可能是几百kb,用户必须耐心等待,直到完全下载完毕。

那么,我们是否应该链接到主体中的样式表,在那里呈现不会被阻塞?你可以这么做,但问题是,阻止租客并不完全是坏事,我们实际上想利用它。如果页面渲染没有任何CSS加载,我们会得到丑陋的“flash无风格的内容”:

2.png

我们想要的最佳点是在哪里渲染,用关键的css阻塞页面,这是设计主视图样式所必需的,但是所有非关键的css都是在初始渲染之后加载的。

关键的CSS

看看我用Bootstrap和Webpack构建的这个简单页面。这是它第一次渲染后的样子:

3.png

该页面还有一个模式,可通过“立即注册”按钮打开。 打开后,它看起来像这样:

4.png

对于页面的第一次呈现,我们需要nav bar、jumbotron、button和其他一些布局和字体的一般规则的css规则。但我们不需要模态的规则,因为它不会立即显示。考虑到这一点,我们可以将关键css与非关键css分离:

critical.css

.nav {
  ...
}

.jumbtron {
  ...
}

.btn {
  ...
}

non_critical.css

.modal {
  ...
}

如果你认同这个概念,你可能会对以下两个问题感兴趣:

  • 我们如何通过编程来区分关键的和非关键的CSS ?

  • 如何让页面在第一次渲染前加载关键的CSS,在第一次渲染后加载非关键的CSS ?

示例项目

我将简要地向您介绍这个项目的基本设置,以便在我们找到解决方案时能够很快地消化。

首先,我加载引导SASS到我的输入文件。

main.js

Favird No-Code Tools
Favird No-Code Tools

无代码工具的聚合器

下载
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: 'style-loader',
          use: ['css-loader', 'sass-loader']
        })
      },
      ...
    ]
  },
  ...
  plugins: [
    new ExtractTextPlugin({ filename: 'style.css' }),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      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), '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,
  }
});

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

内联关键css

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

预加载非关键CSS

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

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

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

将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), 'dist/'),
      src: 'index.html',
      dest: 'index.html',
      inline: true,
      minify: true,
      extract: true,
      width: 375,
      height: 565,
      penthouse: {
        blockJSRequests: false,
      }
    })
  ] 
};

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

性能结果

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

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

在实施关键的CSS:

5.png

关键的CSS实现后:

6.png

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

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

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

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

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

38

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

83

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

97

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

223

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

458

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

169

2026.03.04

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

246

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

34

2026.03.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

CSS教程
CSS教程

共754课时 | 42万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号