CSS的网络性能优化

Posted 达内首都教学部

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSS的网络性能优化相关的知识,希望对你有一定的参考价值。


导   语
CSS的网络性能优化

最近有很多小伙伴都在苦恼css的网络性能问题,然而网上的相关资料却并不多。今天我就结合 CSS 与性能这两大主题,为大家带来一篇文章吧。

CSS的网络性能优化
Q:
什么是CSS?
A:

CSS 是页面渲染的关键因素之一,(当页面存在外链 CSS 时,)浏览器会等待全部的 CSS 下载及解析完成后再渲染页面。关键路径上的任何延迟都会影响首屏时间,因而我们需要尽快地将 CSS 传输到用户的设备,否则,(在页面渲染之前,)用户只能看到一个空白的屏幕。


CSS的网络性能优化


最大的问题是什么?


CSS的网络性能优化

广义而言,CSS 是(渲染)性能的关键,这是由于:
CSS的网络性能优化


浏览器直到渲染树构建完成后才会渲染页面;

渲染树由 DOM 与 CSSOM 组合而成;

DOM 是 html 加上(同步)阻塞的 javascript 操作(DOM 后的)结果;

CSSOM 是 CSS 规则应用于 DOM 后的结果;

使 JavaScript 非阻塞非常简单,添加 async 或 defer 属性即可;

相对而言,要让 CSS 变为异步加载是比较困难的;


CSS的网络性能优化

基于上述考虑,我们需要尽快构建 DOM 与 CSSOM。一般情况下,DOM 的构建是相对较快,(当请求某个页面时,)服务器响应的首个请求是 HTML 文档。但一般 CSS 是作为 HTML 的子资源而存在,因此 CSSOM 的构建通常需要更长的时间。

在这篇文章中,会讲述 CSS 为何是网络瓶颈(无论是对于它自己或是其他资源),该如何突破它,从而缩短关键路径以减少首次渲染前的等待时间。


使用关键 CSS


CSS的网络性能优化
如果条件允许,缩短渲染前等待时间最有效的方式就是使用 Critical CSS (关键 CSS)模式:找出首次渲染所需的样式(通常是首屏相关的样式),将它们内联到 head 标签中,其他样式则通过异步的方式进行加载。



根据媒体类型拆分代码


CSS的网络性能优化
CSS的网络性能优化
CSS的网络性能优化
CSS的网络性能优化



CSS的网络性能优化
如果在项目组难以执行关键 CSS 策略,可以尝试根据媒体查询拆分 CSS 文件,这也是一种可靠的策略。执行此策略后,浏览器表现如下:


以非常高的优先级下载符合当前上下文(设备、屏幕尺寸、分辨率、方向等)的 CSS 文件,阻塞关键路径;

以非常低的优先级下载不符合当前上下文的 CSS 文件,不会阻塞关键路径。


CSS的网络性能优化
浏览器基本上能将未命中媒体查询的 CSS 文件延迟下载。
CSS的网络性能优化



避免在 CSS 文件中使用 @import


为缩短渲染等待时间而努力的下一项任务非常简单: 

如果了解 @import 的原理,那应该清楚它的性能并不高,使用它会阻塞渲染更长时间。这是因为我们在关键路径上创造了更多(队列式)的网络请求:

CSS的网络性能优化


下载 HTML;

请求并下载依赖的 CSS;下载及解析完成后,本该是构造渲染树,然而;

CSS 依赖了其他的 CSS,继续请求并下载 CSS 文件;构造渲染树。


注意:

有一个特殊的情况值得讨论。如果你没有包含@import 的 CSS 文件的修改权限,为了让浏览器并行下载 CSS 文件,可以往 HTML 中补充相应的 <link rel="stylesheet" />。浏览器会并行下载相应的 CSS 文件且不会重复下载 @import 引用的文件


不要将动态插入 JavaScript 的代码放在之后


CSS的网络性能优化



CSS的网络性能优化
在上文中,我们了解到某些引用 CSS 文件路径 的方法,会对其他资源的下载造成负面影响。下面,我们将探究为何稍有不慎,CSS 将延迟其他资源的下载。该问题主要出现在动态创建的 <script> 标签中:


<script>

var script = document.createElement('script');

script.src = "analytics.js";

document.getElementsByTagName('head')[0].appendChild(script);

  </script>


所有浏览器都存在一个鲜为人知,但符合逻辑的现象,它会对性能造成很大的影响:


CSS的网络性能优化
在浏览器下载完该 CSS 文件之前,不会执行下面的 JS


<link rel="stylesheet" href="slow-loading-stylesheet.css" />

<script>

console.log("I will not run until slow-loading-stylesheet.css is downloaded.");

    </script>


这是合理的

当 CSS 文件尚未下载完成时,HTML 文档中任何同步的 JavaScript 代码,均不会执行。考虑以下场景: <script> 中的代码会访问当前的页面样式,为确保结果正确,需要等待( <script> 标签前)所有 CSS 文件下载并解析完毕后再获取,否则无法保证正确性。因此,在 CSSOM 构建完成之前,<script> 中的代码不会执行。

根据这现象,CSS 文件的下载时间会对后续 <script> 的执行时间造成影响。


CSS的网络性能优化

  建   议

如果 <script> 中的代码并不依赖 CSS,把它们放在样式表之前。

将无需查询 CSSOM 的 JavaScript 代码放在 CSS 文件之前,需要查询的放在 CSS 文件之后



这条建议远比你想象中的有用。


CSS的网络性能优化


上文讨论了插入新 <script> 的代码应放在 <link> 之前,那是否能推广到其他的 CSS 与 JavaScript 呢?为了弄明白这个问题,先提出以下假设:


假设 & 答案
假设

1. CSSOM 的构建会阻塞 CSS 后面同步 JS 的执行;

2. 同步的 JS 会阻塞 DOM 的构建…


那如果 JS 并不依赖 CSSOM,
以下那种情况会更快?

1. script 在前 style 在后;

2. style 在前 script 在后?


答案

如果 JS 文件没有依赖 CSS,你应该将 JS 代码放在样式表之前。 既然没有依赖,那就没有任何理由阻塞 JavaScript 代码的执行。

总结


CSS的网络性能优化


以下是我总结的 CSS 加载相关的一系列的最佳实践,值得参考


CSS的网络性能优化

  懒加载非关键 CSS:

CSS的网络性能优化

优先加载关键 CSS,懒加载其他 CSS;

CSS的网络性能优化

或根据媒体类型拆分 CSS 文件。

CSS的网络性能优化

  避免使用 @import:

CSS的网络性能优化

HTML 文档中应该避免;

CSS的网络性能优化

  CSS 文件之中更应避免;

CSS的网络性能优化

以及警惕预加载扫描器的怪异行为。

CSS的网络性能优化

  关注 CSS 与 JavaScript 的顺序:

CSS的网络性能优化

  CSS 文件后的 JavaScript 仅在 CSSOM 构建完成后才会执行;

CSS的网络性能优化

如果你的 JavaScript 不依赖 CSS;

CSS的网络性能优化

  将它放置于  CSS 之前;

CSS的网络性能优化

如果 JavaScript 依赖 CSS:

CSS的网络性能优化

将它放置于 CSS 之后。

CSS的网络性能优化

仅加载 DOM 依赖的 CSS:


CSS的网络性能优化


这将提高初次渲染的速度使让页面逐步渲染


注意

本文叙述的内容都遵循规范或根据浏览器的行为推导得出,然而,你应该亲自进行测试。尽管理论上是正确的,但在实践中可能会有所不同。记得好好测试!

往期文章:





以上是关于CSS的网络性能优化的主要内容,如果未能解决你的问题,请参考以下文章

性能优化

前端性能优化

前端性能优化:雅虎14条优化规则

前端性能优化之--页面渲染优化全面解析

性能优化总结

网页性能优化