性能优化有很多块,我们这里要分享的是css的优化。css性能优化我们讲下面4点:
1. 内联首屏关键CSS(Critical CSS)
性能优化中有一个重要的指标——首次有效绘制(First Meaningful Paint,简称FMP)即指页面的首要内容(primary content)出现在屏幕上的时间。这一指标影响用户看到页面前所需等待的时间,而**内联首屏关键CSS(即Critical CSS,可以称之为首屏关键CSS)**能减少这一时间。
2. 异步加载CSS
// 创建link标签 const myCSS = document.createElement( "link" ); myCSS.rel = "stylesheet"; myCSS.href = "mystyles.css"; // 插入到header的最后位置 document.head.insertBefore( myCSS, document.head.childNodes[ document.head.childNodes.length - 1 ].nextSibling );
media
属性设置为用户浏览器不匹配的媒体类型(或媒体查询),如media="print"
,甚至可以是完全不存在的类型media="noexist"
。对浏览器来说,如果样式表不适用于当前媒体类型,其优先级会被放低,会在不阻塞页面渲染的情况下再进行下载。<link rel="stylesheet" href="mystyles.css" media="noexist" onload="this.media='all'">
与第二种方式相似,我们还可以通过rel
属性将link
元素标记为alternate
可选样式表,也能实现浏览器异步加载。同样别忘了加载完成之后,将rel
改回去。
<link rel="alternate stylesheet" href="mystyles.css" onload="this.rel='stylesheet'">
上述的三种方法都较为古老。现在,rel="preload"这一Web标准指出了如何异步加载资源,包括CSS类资源。
<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">
注意,as
是必须的。忽略as
属性,或者错误的as
属性会使preload
等同于XHR
请求,浏览器不知道加载的是什么内容,因此此类资源加载优先级会非常低。as
的可选值可以参考上述标准文档。
看起来,rel="preload"
的用法和上面两种没什么区别,都是通过更改某些属性,使得浏览器异步加载CSS文件但不解析,直到加载完成并将修改还原,然后开始解析。
但是它们之间其实有一个很重要的不同点,那就是使用preload,比使用不匹配的media
方法能够更早地开始加载CSS。所以尽管这一标准的支持度还不完善,仍建议优先使用该方法。
注意:
这一方法在现在的浏览器中支持度不算乐观,不过我们可以通过loadCSS进行polyfill,所以支持不支持,这都不是事儿。
3. 文件压缩
性能优化时有一个最容易想到,也最常使用的方法,那就是文件压缩,这一方案往往效果显著。
文件的大小会直接影响浏览器的加载速度,这一点在网络较差时表现地尤为明显。相信大家都早已习惯对CSS进行压缩,现在的构建工具,如webpack、gulp/grunt、rollup等也都支持CSS压缩功能。压缩后的文件能够明显减小,可以大大降低了浏览器的加载时间。
4. 去除无用CSS
虽然文件压缩能够降低文件大小。但CSS文件压缩通常只会去除无用的空格,这样就限制了CSS文件的压缩比例。那是否还有其他手段来精简CSS呢?答案显然是肯定的,如果压缩后的文件仍然超出了预期的大小,我们可以试着找到并删除代码中无用的CSS。
一般情况下,会存在这两种无用的CSS代码:一种是不同元素或者其他情况下的重复代码,一种是整个页面内没有生效的CSS代码。对于前者,在编写的代码时候,我们应该尽可能地提取公共类,减少重复。对于后者,在不同开发者进行代码维护的过程中,总会产生不再使用的CSS的代码,当然一个人编写时也有可能出现这一问题。而这些无用的CSS代码不仅会增加浏览器的下载量,还会增加浏览器的解析时间,这对性能来说是很大的消耗。所以我们需要找到并去除这些无用代码。
当然,如果手动删除这些无用CSS是很低效的。我们可以借助Uncss库来进行。Uncss可以用来移除样式表中的无用CSS,并且支持多文件和JavaScript注入的CSS。