Chrome 中的 First Meaningful Paint

在做网页的性能监控时,首屏加载时间是必不可少的统计项。但是到底如何算是首屏呢?怎么能更好的统计首屏时间呢?lighthouse中的First Meaningful Paint或许能给我们启发。

Chrome 60中正式引入了lighthouse,放在了devtool的audit面板中。lighthouse可以用来对页面进行审查,得到性能等一些数据,最近在看其源码,感觉可以帮助对浏览器渲染页面等有更深的理解,以后可以详细介绍一下。今天要说的是lighthouse中的First Meaningful Paint。

First Meaningful Paint简介

First Meaningful Paint,是lighthouse中performance下的一项审查,可以用来衡量页面的渲染性能。

first meaningful paint

First Meaningful Paint是指页面的首要内容(primary content)出现在屏幕上的时间。对于不同的站点,首要内容是不同的,例如:

  • 对于博客文章:大标题+首屏文字是首要内容
  • 对于百度或者google的搜索结果页:首屏的结果卡片就是首要内容
  • 而对于淘宝等购物网站来说:图也会变得很重要

需要注意的是,通常首要内容是不包括headers和导航条的。

基本计算方法:计算布局对象

在Chrome浏览器中进行渲染时,布局对象会不断地增加到布局树中:

firstMeaningfulpaint02.png

随着布局对象的增加,页面也会一点点被加载出来:

firstMeaningfulpaint03.png

该算法的作者通过观察发现,布局对象的变化跟页面渲染进度非常相关。布局对象变化最显著的时间,与页面主体渲染出的时间非常接近。

于是,作者得到了基本算法,也就是:

首次有效绘制 = 具有最大布局变化的绘制

补充方法:启发法

当然事情没有这么简单,网站这么多种,总会有特例。作者用启发法来cover了一些特例。

长页面

首先是长页面,下图是新浪微博的渲染过程截图。

firstMeaningfulpaint04.png

可以看到页面其实在很早就已经加载完成了,但是最大布局对象的变化发生在二十多秒。原因是微博进行了懒加载,将页面底部的内容,以及背景边框的加载进行了推迟。显然这些内容不能算作首要内容。为了cover这种情形,作者提出了布局显著性,页面越长,显著性系数越小。

布局显著性 = 添加的对象数目 / max(1, 页面高度 / 屏幕高度)

经过处理后,结果如下图所示:

firstMeaningfulpaint05.png

变化最大的地方便接近了首次有效绘制的正确时间。

网页字体

有些网站会加载特殊的字体,例如msn:

firstMeaningfulpaint07.png

最大布局改变时间发生在2.51s,但此时页面中并没有文字显示,因为字体还在加载中。

在文字加载过程中,浏览器会使用字体队列中后方的字体,但是在font block period中,并不会渲染。

显然文字对于页面的渲染非常重要,因此如果在布局发生时有字体正在渲染,那么会将时间推迟直到字体显示出来(字体加载成功了或者到达3秒使用了备用字体)。

实现

首次有效绘制很好,计算看起来也很简单,但是如何获得布局对象的数目呢?

作者实现了两种方法,lighthouse中使用的是chrome渲染过程中记录的trace event

结果

这种基于布局来近似计算首次有效渲染的方法,准确率可以达到77%。具体对比可以看https://docs.google.com/spreadsheets/d/1FEcDwXfgMf5rw1lNn07Cm04A-r7AdPzmt0aAufMsnnk/edit?usp=sharing

firstMeaningfulpaint06.png

参考文献

  1. The New Chrome DevTool Feature You Want to Know About
  2. Time to First Meaningful Paint: a layout-based approach