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

Runwayml(AI painting)
Runwayml(AI painting)

Runway 平台的文本生成图像AI工具

下载
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

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

豆包大模型
豆包大模型

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

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

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

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

23

2026.03.06

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

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

68

2026.03.05

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

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

162

2026.03.04

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

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

84

2026.03.04

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

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

113

2026.03.03

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

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

29

2026.03.03

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

79

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

62

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

51

2026.02.28

热门下载

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

精品课程

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

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.5万人学习

CSS教程
CSS教程

共754课时 | 40.2万人学习

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

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