Karam
Articles34
Tags31
Categories11
首次加载的优化

首次加载的优化

CSS渲染方面

为什么要研究渲染树,因为只有知道了渲染的过程,才能从根源去优化首次加载的速率。
首先建一个非常简单的html文件,然后把用浏览器查看它的性能分析,最后总结出它的渲染过程应该是

从这个图就可以分析出大致的渲染流程:

  1. 渲染进程或者浏览器进程发起加载主界面的请求,去请求HTML文件,将请求发送给网络进程

  2. 请求回来以后,网络进程接收到响应,网络进程和渲染进程建立通道,发送响应数据

  3. 交给渲染进程去构建DOM

    这里的请求过程中是一段空闲时间,很可能称为渲染卡顿的原因

  4. 当渲染进程接收到HTML字节流的时候,当遇到css文件或者JS文件就会开始下载,也就是预解析线程

  5. 当css文件下载完成,进入CSSOM开始构建布局树

    在请求css文件,等待响应的过程,渲染流水线会等待直到网络进程收到css响应,发送给渲染进程才开始构建布局树渲染,这一段时间也是空闲的,可能称为页面白屏的原因

从界面加载到显示的Timing

下面图显示了从五个关键的Timing,DomContentLoaded -> First Paint -> First Contentful Paint -> onLoad -> First Meaningful Paint

这五个关键的时间节点的流程分别是:

  1. 浏览器加载Html文件,解析Html完成后触发DCL【DomContentLoaded】,此刻还没有开始加载像css,图片这样的静态文件
  2. 浏览器开始渲染直出的Html触发FP 【First Paint】接着触发FCP 【First Contentful Paint】,用户开始可以看见文字
  3. 浏览器把图片等静态资源加载过来了,所有资源都加载完成,触发L 【OnLoad】
  4. setTimeout触发,往界面中写入大量DOM,触发FMP 【First Meanful Paint】

为什么需要CSSOM

渲染进程无法理解css文件,需要和DOM树类似的结构类文件才能理解,所以先要把css文件构建成CSSOM,所以CSSOM的作用就有两个:一个是使JavaScript有操作csss的能力,另一个是构建布局树,指定样式,CSSOM在dom中体现就是document.stylesheet,计算完样式以后,还要计算布局,计算每个元素的几何位置,绘制完布局树就可以开始渲染了。

复杂场景

当我在代码中加入一些内联脚本,渲染的过程就变为:

因为内联脚本可能会改变CSSOM,影响渲染,所以会先执行内联脚本,再构建布局树,DOM树

如果代码中间穿插内联的脚本外部引用,那么就会在构建dom期间预解析线程,请求Javascript文件,然后等到构建好CSSOM,再解析Javascript脚本,继续构建DOM

如何获取首屏时间

我们称浏览器从输入url到第一次渲染出界面的时间为首屏时间,首屏时间不止是加载Javascript和css文件的时间,还有Javascript的执行时间,所以要获取比较准确的首屏时间,最好使用Resource Timing API来计算,尽量使用内联css文件,避免css阻塞Javascript的执行

如何优化首屏加载

一般认为用户满意的首屏加载时间在2s左右,我们写优化应该要把首屏时间控制在2s以内,保证用户体验。HTML文档的首屏大小要控制在14kb左右
主要有下面三个问题:

  1. 下载CSS文件
  2. 下载Javascript文件
  3. 执行Javascript

解决方法:

  • 清除内联的CSS和JavaScript,避免浏览器在渲染过程中预解析线程下载css和Javascript
  • 尽量减少Javascript文件的大小,通过webpack打包优化Javascript的代码
  • 在一些不必要使用的Javascript文件下使用属性async和defer来延迟加载文件
  • 对于比较大的CSS文件,可以设置媒体查询,只在特定场景下使用css文件

content-visibility

这个属性可以影响浏览器的渲染,控制元素渲染延迟,可以很好优化首屏加载,但是它和display:none和visibility有点类似,如果使用了他,浏览器就无法计算元素的高度,如果界面元素超出,滚动就会变得奇怪,所以可替代的,有了content-intrinsic-size来确保正确的渲染,它会给元素一个高度占有,像一个占位符

避免使用@import导入样式表

@import使用网络请求来导入样式表,会妨碍渲染,而使用link导入css可以并行加载文件

资源请求优化

像第一次进行项目优化就是针对资源请求进行优化的,主要是模块的按需加载和代码压缩

  • 页面预加载

静态资源缓存优化

  • 模块资源缓存
  • 模块按需加载

数据请求优化

根据算法,如埋点,个性化推荐等,减少数据请求

为什么说首屏HTML文档要控制在14kb

因为HTTP在发送请求的时候会使用慢启动,慢启动会限制发送速率,在首次建立TCP连接的时候,TCP最多只能发送10个TCP数据包(约为14kb),所以为了更好的利用网络带宽,我们应该尽量将首屏的HTML文档控制在14kb左右