文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

A website stage setting

在互联网的早期,网站展示的内容主要是文本信息。随着后期的逐步发展,网络连接速度有了大幅提升,用户能以较快的速度下载高分辨率图像及视频。如今,网站插件越来越多,如 CSS 和 Javascript 框架。网站信息越来越丰富多样,展现形式也不再局限于文本形式。要想展示所有形式的信息,在内容加载上,必然要花费些时间。

网站流畅度越佳,则用户体验越佳,这无疑是网站成功构建的关键。那么,开发人员需要如何工作才能提升网站性能呢?他们能做的一件事就是内联关键 CSS 及加载非关键 CSS。在本文中,我们将对这类问题进行逐一介绍,以帮你提升网站性能。

第 1 段(可获 1.88 积分)

什么是关键 CSS?

项目的关键 CSS 是指对网站首页内容进行样式设计的 CSS。当用户打开一个网站,他们最先看到的就是首页的内容,它包括了导航和其他一些元素。因此,对首页内容进行合理设计及排版非常重要。

首先,我要提的一点是,当用户对你的网站进行访问时,他们使用的设备五花八门,可视端口也会各不相同。而首页又无法自动调整页面的布局及内容。因此,为解决这一问题,根据不同设备选择对应的 CSS 就变得至关重要。

第 2 段(可获 1.51 积分)

根据现代 web 开发实践的经验,我建议你内联关键 CSS,并将它放置在网站上,如:

<!doctype html>
<html>
  <head>
    <title>An Optimized Web Page</title>
    <style type="text/css"> (Your minified critical CSS would be here) </style>
  </head>
  <body>
     (Your markup)
  </body>
</html>

内联有何必要性?

如果你访问 Google PageSpeed Insights [译者注:谷歌的网页速度分析工具],并将你的网页放上去进行分析测试,你可能会收到关于优化 CSS 投放的警告——请内联关键  CSS 并异步加载渲染时阻塞页面的样式表。

第 3 段(可获 0.74 积分)

在浏览器对所有的 CSS 文件完成加载之前,它不会对网站首页的内容进行呈现。当有很多文件需要加载时,这会是个大工程。

并非所有用户的网络连接速度都很快。当有些用户打开网站想要浏览内容时,却发现还要等待库、CSS 和 JavaScript 框架完成加载,这过程真是让人扫兴。即使是处于网速很快的环境,在某种情况下也会有断网的可能,就好比突然进入了一个隧道。但是,如果你的网站内联了关键 CSS,并且在显示主要内容之前没有加载其他文件,你仍可以看到网站的主要内容。

第 4 段(可获 1.49 积分)

以下的图示详细说明了普通页面和优化页面的区别。如你所见,优化版本能让用户提前约 0.5s 的时间看到内容。当有许多其他的库需要加载时,这一改进的效果会更明显。

Inline CSS loading stages

什么时候需要内联关键 CSS?

这得视情况而定。假如网站没有使用到重量级框架或者库,且 CSS 文件非常小,这种情况则没有内联 CSS 的必要。

如果你使用的是诸如 Bootstrap 的框架,但你只使用了该框架的部分功能。这时,你可以从框架的样式表中提取出关键 CSS,并以异步方式加载原来框架。这样做,可以明显提高该网站的访问速度。

第 5 段(可获 1.75 积分)

内联时,你可将样式表缓存下来。而 HTML 通常不缓存(并且不建议这样做)。这意味着两者之间存在差异,在进行更新的时候,务必记住这点。另外,在用户访问网站时,内联 CSS 会导致页面负载增加。比如,假设网站每页有 30 KB 的内联 CSS,如果每个用户浏览 10 个页面,那么就会增加 300KB 内存。这听起来似乎不是大事,但在某些地方,流量数据是非常贵的(在 3G/4G 环境中)。注意,你要确保你只内联关键 CSS 到 web 页面,而不是内联所有事项

第 6 段(可获 1.65 积分)

发现关键 CSS

手动发现关键 CSS 工作很艰巨,但是很无聊。幸运的是,有相关工具可以帮你快速查找关键 CSS。

使用 Grunt

如果你足够熟悉 Grunt 构建体系,你就会发现,这里有一个 grunt-critical 插件,它能简化查找过程,加快查找速度。(如果你更偏向于使用 Gulp 或 npm 的话,请查看下一部分的内容,我稍后会做详细介绍。)

首先,按照以下命令安装插件:

npm install grunt-critical --save-dev

然后创建 Gruntfile.js。它包含了设置插件各类选项的所有代码,包括视窗尺寸、源文件和目标文件的路径。示例如下:

第 7 段(可获 1.43 积分)
module.exports = function(grunt) {

  grunt.initConfig({
    critical: {
      extract: {
        options: {
          base: './',
          width: 1024,
          height: 768,
          minify: true
        },
        src: 'path/to/initial.html',
        dest: 'path/to/final.html'
      }
    }
  });

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

};

在包装函数中,我们使用 grunt.initConfig 方法来指定所有配置选项。然后,我指定了要写入源文件和目标文件的基本目录,再将 minify 选项设置为 true。之后我会得到通过插件提取的关键 CSS 的最终压缩版。src 属性包含接下来要操作的源文件的位置。dest 属性包含需要保存的最终输出的位置。

第 8 段(可获 1.04 积分)

如果 dest 文件是样式表,则生成的 CSS 将保存为文件以供将来使用。然而,如果 dest 属性是标记文件(如 HTML,PHP 等等),那么 CSS 将被内联,现存的样式表会被包装在 JavaScript 函数中以进行异步加载。如果用户的 JavaScript 被禁用,dest 会为其添加 noscript 模块。除此之外,当然还有其他选项可用,你可访问关键项文档查看完整选项列表。

现在,你可以在控制台输入 grunt 运行插件:

C:\path\to\project>grunt
第 9 段(可获 1.16 积分)

如果初始文件含有以下标记:

<!doctype html>
<html>
  <head>
    <title>The Optimizer</title>
    <link rel="stylesheet" href="link/to/stylesheet">
  </head>
  <body>
     <div>All the markup stuff</div>
  </body>
</html>

之后会出现:

<!doctype html>
<html>
  <head>
    <title>The Optimizer</title>
    <style type="text/css">Minified Inlined CSS</style>
    <script id="loadcss">
       JavaScript to load styles asynchronously...
    </script>
    <noscript>
      <link rel="stylesheet" href="link/to/stylesheet">
    </noscript>
  </head>
  <body>
     <div>All the markup stuff</div>
  </body>
</html>
第 10 段(可获 0.16 积分)

如你所见,此插件为你执行所有操作。现在,如果你再次使用 PageSpeed 分析网页,相信你会得到一个可观的分数。据我猜测,这个分数大概会从起初的 86 涨到 95。

还有一些其他插件也适用 Grunt,同样也能实现 grunt-criticalcss 和 grunt-penthose 的功能。然而,在使用这些插件时,你必须指定提取关键 CSS 的样式表。

使用 npm 模块

Critical 是一个由 Addy Osmani 创建的 npm 模块,grunt-critical 插件会使用与它相同的功能。它可以在 Grunt 环境之外运行,通过 JavaScript 和 npm,提取并内联关键路径,或Web页首屏CSS。可以运行如下命令安装这个包:

第 11 段(可获 1.56 积分)
npm install critical --save-dev

安装这个包之后,还需要在项目目录下创建一个 JavaScript 文件,写入如下代码:

var critical = require('critical');

critical.generate({
  inline: true,
  base: 'initial/',
  src: 'homepage.html',
  dest: 'final/homepage.html',
  width: 1366,
  height: 768
});

你可以指定一组选项来创建优化的网页。将 inline 设置为 true 会在产生的 HTML 页面中内联 CSS,相反则会产生一个 CSS 文件。width 和 height 选项设置目的视区的范围。还有很多其它选项,比如最小化内联 CSS 的,这些都可以在 Critical npm 包的文档中找到。优化后的网页看起来和使用  Grunt 插件输出的差不多。

第 12 段(可获 1.31 积分)

另外还有一个 critical-css 的 npm 模块可用。这个模块会从给定的 URL 生成关键 CSS。可以通过一个回调函数进行处理生成的CSS,因为grunt 插件就是基于这个包的。

使用Gulp

如果你更喜欢使用 Gulp,Addy Osmani 建议Gulp 用户直接使用npm的 Critical 模块。它在 Critical GitHub 页面上提供了一个示例给 Gulp 用户:

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

// Generate & Inline Critical-path CSS
gulp.task('critical', function () {
  return gulp.src('dist/*.html')
    .pipe(critical({base: 'dist/', inline: true, css: ['dist/styles/components.css','dist/styles/main.css']}))
    .pipe(gulp.dest('dist'));
});
第 13 段(可获 1 积分)

Critical 团队也通过 一个 Gulp 项目示例 来展示了这个操作。

还有一个 gulp-critical-css 插件用于生成关键 CSS。但是这个插件会抽取某些选择类型来处理,而不是检测首屏页面中的元素来处理。

更多的资源

还有一个由 Jonas Ohlsson 创建的工具,叫 Critical Path CSS Generator。你需要做的仅仅是输入页面 的URL,并提供你想抽取关键部分的 CSS。然后点击 “Create Critical Path CSS” 按钮,就能得到想要的输出。

 

第 14 段(可获 1.21 积分)

CSS技巧文章概述了如何 使用 CSS 预处理器创建关键的CSS。另外,SitePoint 也发表了一篇不错的文章,是关于优化关键渲染路径的,它可以帮助你更深层地理解本文讨论的内容。

结论

更多学习资源

是否内联 CSS ,关键取决于用户的访问模式和网站的结构。在下述两种情况下,内联 CSS 能显著提高性能:第一,网站是单页,且访问者不多;第二,网站使用了复杂的网站框架和插件。

 

第 15 段(可获 1.41 积分)

内联唯一的问题在于,它为每个访问页面增加了额外的负担。不过这可以在第一次使用 cookie 和发送关键 CSS 时,使用异步加载完整的 CSS 文件和缓存来减轻负担。尽管这有些复杂,不过对你来说可是一举两得

在你的项目中你是否尝试使用内联CSS了吗? 有重要的改善吗?你对其他开发人员有什么建议吗?请在评论中告诉我们。

第 16 段(可获 1.05 积分)

文章评论