今天我们来讨论一下网页首次渲染FP(First Paint).
W3C定义:First Paint entry contains a DOMHighResTimeStamp reporting the time when the browser first rendered after navigation. This excludes the default background paint, but includes non-default background paint. This is the first key moment developers care about in page load – when the browser has started to render the page.
意思:首次渲染即用户输入URL后浏览器中第一次进行网页绘制的时刻,它不包括浏览器默认的网页背景绘制,但是包括开发者自定义网页背景绘制。
下面我们通过几个实验来感受一下首屏时刻:
实验一:没有背景,没有文字,仅包含DIV
<!DOCTYPE html>
<html lang="en">
<head>
<title>FP测试</title>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>
浏览器没有进行任何绘制,此时不存在首屏时刻
实验二:给DIV增加背景色
<div id="div1" style="height: 50px; background-color: red;"></div>
浏览器进行首屏绘制,完成div1节点的渲染,但是发生时刻在DCL(DOMContentLoaded)之前
实验三:DIV里同时包含文字和背景
<div id="div1" style="height: 50px; background-color: red;">
我的DIV1我的DIV1我的DIV1我的DIV1我的DIV1
</div>
浏览器进行首屏绘制,但是因为有文字存在,所以同时触发FCP和FMP时刻
实验四:增加内联JS脚本,将其放在body中的两个DIV之间
<div id="div1" style="height: 50px; background-color: red;">
我的DIV1我的DIV1我的DIV1我的DIV1我的DIV1
</div>
<script>
(function(){
for(var i=0;i<1000000;i++){
document.querySelector("#div1");
}
})()
</script>
<div id="div2" style="height: 50px; background-color: green;">
我是DIV2我是DIV2我是DIV2我是DIV2我是DIV2
</div>
<div id="div3"></div>
浏览器首屏绘制div1和div2节点,没有受到内联JS脚本的影响
实验五:增加外联同步JS脚本,将其放在body中两个DIV之间
<div id="div1" style="height: 50px; background-color: red;">
我的DIV1我的DIV1我的DIV1我的DIV1我的DIV1
</div>
<script src="https://www.tripfe.cn/assets/built/jquery-3.2.1.min.js?v=73e3b39e65"></script>
<div id="div2" style="height: 50px; background-color: green;">
我是DIV2我是DIV2我是DIV2我是DIV2我是DIV2
</div>
<div id="div3"></div>
浏览器首屏仅绘制div1节点,没有绘制div2节点,这说明外联同步JS会阻塞DOM解析使得首屏时刻提前到来
实验六:增加外联异步JS脚本,将其放在body中两个DIV之间
<div id="div1" style="height: 50px; background-color: red;">
我的DIV1我的DIV1我的DIV1我的DIV1我的DIV1
</div>
<script async src="https://www.tripfe.cn/assets/built/jquery-3.2.1.min.js?v=73e3b39e65"></script>
<div id="div2" style="height: 50px; background-color: green;">
我是DIV2我是DIV2我是DIV2我是DIV2我是DIV2
</div>
<div id="div3"></div>
浏览器首屏绘制div1和div2节点,且没有受到外联异步JS脚本的影响。
实验七:增加外联同步JS脚本,将其放在body最上面
<script src="https://www.tripfe.cn/assets/built/jquery-3.2.1.min.js?v=73e3b39e65"></script>
<div id="div1" style="height: 50px; background-color: red;">
我的DIV1我的DIV1我的DIV1我的DIV1我的DIV1
</div>
<div id="div2" style="height: 50px; background-color: green;">
我是DIV2我是DIV2我是DIV2我是DIV2我是DIV2
</div>
<div id="div3"></div>
浏览器完成首屏绘制的时刻在同步脚本加载完成之后,且绘制了div1和div2节点,FP时刻大于DCL时刻
实验八:增加外联css文件,将其放置在body最下面
<div id="div1" style="height: 50px; background-color: red;">
我的DIV1我的DIV1我的DIV1我的DIV1我的DIV1
</div>
<div id="div2" style="height: 50px; background-color: green;">
我是DIV2我是DIV2我是DIV2我是DIV2我是DIV2
</div>
<div id="div3"></div>
<script>
(function(){
for(var i=0;i<1000000;i++){
document.querySelector("#div1");
}
})()
</script>
<link rel="stylesheet" href="./c2.css" />
// ./c2.css
#div3 {
height: 50px;
background-color: cyan;
}
浏览器完成首屏绘制,同时绘制了div1、div2、div3三个节点,说明外联css会阻塞首屏绘制
总结
近年来,首屏时间变得越来越重要,它代表在用户请求一个页面后可能展现某些东西的最早时间。虽然页面加载时会同时跑很多任务,但是我们都知道,只有当我们越快地在页面上展现某些东西给用户,才会越快地让他们意识到某些工作正在进行。
评论