performance-column
performance-column copied to clipboard
性能优化之内联 CSS
申领人须知
- 搞清楚 CSS 渲染的时机,构建 CSSOM 的流程
- CSS 内联如何做,工程化体系中如何体现
首先了解阻塞渲染的 CSS
了解css的渲染时机,首先我们需要了解在浏览器中看到一个html页面之前的渲染过程
- url 解析(http三次握手,浏览器缓存机制,内容下载)
- 解析html代码,自上而下,发起页面内部引用资源css,js,img的下载请求(同时会再次进行上面的步骤对资源url解析)
- 生成html dom 以及 cssom(css object model),结合htmldom 和 cssom 生成 render tree
- layout (布局)根据渲染树来布局,以计算每个节点的几何信息
- paint (绘制)将各个节点绘制到屏幕上
第一步到第五步的进行是同步的,任何一步的执行时间都决定着整个页面出现在你面前的时间,默认css的渲染也是阻塞性的,同时具有 DOM 和 CSSOM 才能构建渲染树。那么接下来我们就来探讨一下如何优化阻塞css。
优化阻塞的外链css文件
CSS 是阻塞渲染的资源。需要将它尽早、尽快地下载到客户端,以便缩短首次渲染的时间。
我们可以通过 CSS“媒体类型”和“媒体查询”来解决这类用例:
<link href="style.css" rel="stylesheet">
<link href="style.css" rel="stylesheet" media="all">
<link href="print.css" rel="stylesheet" media="print">
<link href="portrait.css" rel="stylesheet" media="orientation:portrait">
<link href="other.css" rel="stylesheet" media="(min-width: 40em)">
- 第一个和第二个声明阻塞渲染,适用于所有情况。
- 第三个声明只在打印网页时应用,因此网页首次在浏览器中加载时,它不会阻塞渲染。
- 第四个声明具有动态媒体查询,将在网页加载时计算。根据网页加载时设备的方向,portrait.css 可能阻塞渲染,也可能不阻塞渲染。
- 第五个 只有当前窗口宽度大于等于 40em 时才会阻塞渲染
但是请注意,“阻塞渲染”仅是指浏览器是否需要暂停网页的首次渲染,直至该资源准备就绪。无论哪一种情况,浏览器仍会下载 CSS 资产,只不过不阻塞其它渲染的资源而已。
内联关键css
何为关键css呢?根据首屏优先的原则,关键css就是初始化首屏页面所用到的css。 内联的好处一是节省请求,二是不会阻塞渲染,唯一的缺点是增加了首次html内容的下载时间,但是如果做了页面缓存,除了首次稍微有影响外,其它时间几乎可以忽略。
如果每次手动发现去复制粘贴首屏部分的css代码,无疑是比较枯燥的事情,还好有相关工具可以帮你快速查找关键 CSS。
首先安装插件
npm install critical --save-dev
这里以gulp为使用案例进行配置
var critical = require('critical').stream
gulp.task('critical', function () {
return gulp.src(path.join(filePath, 'map.html'))
.pipe(critical({
base: 'dist/',
inline: true,
width: 1200,
height: 640,
src: 'map.html',
dest: 'map-critical.html',
css: [path.join(filePath, 'src/css/main.css')]
}))
.on('error', function(err){
console.log(err)
})
.pipe(gulp.dest(filePath));
});
除了gulp之外也可以和grunt,npm配合使用
参考资源: https://developers.google.cn/web/fundamentals/performance/critical-rendering-path/render-blocking-css?hl=zh-cn https://www.sitepoint.com/how-and-why-you-should-inline-your-critical-css/
另外css的优化还可以做本地化 异步读取css文件内容,然后内联到页面中,同时利用localstorage存储到本地,下次访问页面判断如果localstorage中存在就直接取,如果被用户清除了,再重新异步加载
将css内联到html之后,应该要注意到html文件的大小,由于tcp慢启动的原因,不推荐内联后的文件大小超过14KB,否则会消耗更过的RTT耗时