网页首次渲染FP

网页首次渲染FP

今天我们来讨论一下网页首次渲染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会阻塞首屏绘制

总结


近年来,首屏时间变得越来越重要,它代表在用户请求一个页面后可能展现某些东西的最早时间。虽然页面加载时会同时跑很多任务,但是我们都知道,只有当我们越快地在页面上展现某些东西给用户,才会越快地让他们意识到某些工作正在进行

风清洋

风清洋

保持原动力,迎接每一天

评论