前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Chrome的First Paint触发的时机探究

Chrome的First Paint触发的时机探究

作者头像
用户1749219
发布于 2018-07-05 07:45:13
发布于 2018-07-05 07:45:13
1.9K10
代码可运行
举报
运行总次数:0
代码可运行

前言

First paint 直译过来的意思就是浏览器第一次渲染(paint),在First paint之前是白屏,在这个时间点之后用户就能看到(部分)页面内容。

所以研究这个First Paint的触发时机对于优化浏览器页面的首屏渲染时间有很重要的作用。

在正题开始之前,先说下浏览器的页面的加载流程(大体过程是这样,并不精确,只是为了帮助理解后面内容):

  1. 浏览器输入url,浏览器发送请求到服务器,服务器将请求的HTML返回给浏览器。
  2. 浏览器下载完成HTML(Finish Loading HTML)之后,便开始从上到下解析。
  3. 解析的过程中碰到css和js外链(其实HTML的下载也是这个流程)都会执行以下过程:
    1. Send Request:表示给这个外链对应的服务器发送请求
    2. Receive Response: 表示接收响应,这里是表示告诉浏览器可以开始从网络接收数据了
    3. Receive Data:表示开始接收数据
    4. Finish Loading: 表示已经完成下载数据。
    5. Parse Stylesheet/Evaluate(默认情况下js下载完成之后执行Evaluate,css下载完成后会进行Parse Stylesheet
  4. 所有的css下载完成后Parse Stylesheet然后开始构建CSSOM
  5. DOM(文档对象模型)和 CSSOM(CSS对象模型)会合并生成一个渲染树(Render Tree)
  6. 根据渲染树的内容计算处各个节点在网页中的大小和位置(Layout,可以理解为“刻章”)
  7. 根据Layout绘制内容在浏览器上(Paint,可以理解为“盖章”)。

正题开始

在最新版的Chrome的perfomance中是能直接看到First Paint这个时间点的,为了方便大家测试,我就直接拿谷歌这个示例页面来做演示:

测试页面

用chrome打开上面链接,最好是隐身模式,防止插件乱入影响判断,按F12或者右键检查元素打开控制台先切换到Network选项,勾选禁用缓存(缓存也会影响到判断):

切换到Perfomance,勾选Screenshots并点击红框进行页面分析(会自动停止的,不用点stop):

分析完后可以看到如下结果:

上图中的绿色的线就是当前页面第一次出现内容的时间点,可以将鼠标放到Main上面的Network中绿色的线附近可以看到在他之前页面空白,在他之后就有内容。 除了绿色的线还有蓝色以及红色的线,这里也解释一下:

简单讲一下DOMContentLoadedload的区别:

  1. DOMContentLoaded是HTML文档(包括CSS、JS)被加载以及解析完成之后触发(即 HTML->DOM的过程完成 )
  2. load则是在页面的其他资源如图片、字体、音频、视频加载完成之后触发
  3. load事件一般在DOMContentLoaded之后才触发(也有可能在它之前哦)

这个时候发现绿色虚线之前有一个浅绿色方块,相应的解释如下:

由图可以得出“浅绿色”代表的是根据CSSOM计算样式并进行布局绘制的过程,这段时间内浏览器做了一下事情:

  1. Recalculate Style:重新计算样式,确定DOM元素的样式规则(定规则)
  2. Layout:根据计算结果进行布局,确定元素的大小和位置(刻章)
  3. Update Layer Tree: 更新渲染层树
  4. Paint: 绘制,根据前面的Layer Tree绘制页面(位置、大小、颜色、边框、阴影等)(盖章)
  5. Composite Layers: 形成层,浏览器按照合理的顺序合并成一个图层然后输出到屏幕(给别人看)

那什么时候开始First paint呢?在浅绿色方块最前面的虚线往前看,发现在灰色虚线之前都会有一个步骤:就是Parse Stylesheet(调研了很多页面都是如此)

所以,First Paint的加载流程应该是这样:

  1. 所有的CSS加载完成
  2. Parse Stylesheet:构建出CSSOM
  3. Recalculate Style:重新计算样式,确定DOM元素的样式规则(定规则)
  4. Layout:根据计算结果进行布局,确定元素的大小和位置(刻章)
  5. Update Layer Tree:更新渲染层树
  6. Paint:绘制,根据前面的Layer Tree绘制页面(位置、大小、颜色、边框、阴影等)(盖章)
  7. Composite Layers:形成层,浏览器按照合理的顺序合并成一个图层然后输出到屏幕(给别人看)

但是现在还只是确定了First Paint的加载流程,也确定了他是在所有CSS执行完Parse Stylesheet之后才会触发,但是这还是不够准确啊,所以我找了一些CSS和JS的外链来测试,模板如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.css" rel="stylesheet">
    <link href="https://cdn.bootcss.com/jqueryui/1.12.1/jquery-ui.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script src="https://cdn.bootcss.com/react/16.4.0-alpha.0911da3/cjs/react.development.js"></script>
    <script src="https://cdn.bootcss.com/angular.js/2.0.0-beta.17/angular2.js"></script>
</head>
<body>
    <div id='root1'>
        1
    </div>
    <div id='root2'>
        2
    </div>
    <div id='root3'>
        3
    </div>
</body>
</html>

我们通过改变上面模板里的外链顺序来探究:

第一种情况:

发现FP发生在最后(实心的蓝色线是按shift出来的,不是DOMContentLoaded),现在还发现不了什么。

第二种情况:

调换head中CSS和JS外链位置

仍然发现不了什么

第三种情况

把CSS放head,JS放</body>

发现FP竟然在蓝色和红色虚线前面出现,通过这点可以确定,FP还跟JS外链的位置有关,继续:

第四种情况:

JS外链放head,CSS放</body>

发现又跟第一二种情况一样了,所以这种用法是不可取的。

第五种情况:

CSS和JS都放</body>前,且CSS紧贴在div后面,JS在CSS后面:

可以发现FP居然更快触发,但是我鼠标hover到绿色虚线后,仍然是白屏,只有等到CSS加载完成执行Parse Stylesheet之后才显示出内容(说明这种用法也不可取),难道body中的CSS也会影响?

第六种情况:

掉换一下上面CSS和JS的位置:

发现这次FP触发而且立马有内容,而等到CSS加载完成之后还会再重新渲染一次,嗯,看来body中的第一个JS脚本有猫腻,接下来的情况对他特殊照顾。

第七种情况:

CSS放head中,JS放在div节点中间:

哈哈,居然只渲染了12俩字,说明浏览器会渲染body中脚本之前的内容,那会是哪个脚本之前的内容呢?

第八种情况:

在div之间都插入脚本

看来浏览器会提前渲染body中第一个脚本前的内容(我们就把body中的第一个外链脚本叫做【第一脚本】吧),并且第一脚本还会在FP之后才执行。所以结合之前得出的结论,在CSSOM准备就绪之后,浏览器会提前渲染第一脚本前的内容,我们可以用第九种情况来验证:

第九种情况:

这种情况和上种没什么区别,只是增加了一个CSS,这个CSS中还会发出一个请求去加载其他CSS(通过@import url()的方式),所以CSS的加载时间很长。

通过结果可以看出,123在CSS下载完成之后才渲染,而不是单独渲染一个1,所以FP必须得等到CSSOM准备就绪之后才会触发,否则即使有第一脚本在也没用。 所以到这里,我们总算可以下结论了:

FP发生在body中第一个script脚本之前的CSS解析和JS执行完成之后。换句话说就是第一脚本之前的DOMCSSOM准备就绪之后,便会着手渲染第一脚本前的内容。

但是...你以为到这里就结束了?其实没有。

第十种情况:

这种情况中,head中既有JS也有CSS,body中也有第一脚本存在:

注意上图中的vue.js是在head中的,而后面的JS文件都在body中,而且,vue.js加载完成之后,body中的JS还没下载完成,这个时候我们调换一下vue.jsangular2.js的位置:

看,这个时候又没有提前渲染了,123等到所有JS文件都执行完之后才渲染,这种情况除了验证了第九点的结论,还能补充我们的结论:

如果第一脚本前的JS和CSS加载完了,body中的脚本还未下载完成,那么浏览器就会利用构建好的局部CSSOMDOM提前渲染第一脚本前的内容(触发FP);如果第一脚本前的JS和CSS都还没下载完成,body中的脚本就已经下载完了,那么浏览器就会在所有JS脚本都执行完之后才触发FP。

到这里本次探究就结束了,其实还有很多种情况,感兴趣的可以自己去试试。

建议:

  • CSS放在head中,JS放在</body>前(如果在head必须放JS,也尽量减少他的大小,把大JS文件放</body>前)。
  • 减小head中CSS和JS大小(gzip了解一下?),
  • 优化head中的JS和CSS外链的网络情况,减少StalledTTFBContent Download的时间。
  • 在第一脚本前使用骨架图,可以减少用户的白屏感知时间(对于使用JS插入模板来渲染的框架,建议将骨架图的路由生成逻辑单独提出来)

科普一下

  • Chrome会渲染局部CSSOMDOM
  • First PaintDOMContentLoadedload事件的触发没有绝对的关系,FP可能在他们之前,也可能在他们之后,这取决于影响他们触发的因素的各自时间(FP第一脚本CSSOMDOM的构建速度;DOMContentLoadedHTML文档自身以及HTML文档中所有JSCSS的加载速度;load:图片、音频、视频、字体的加载速度)。
  • DOMContentLoadedload事件也没有强制的先后顺序,DOMContentLoaded一般在load事件之前触发,但也可能在load事件之后触发。
  • 第一脚本前的CSS如果还会去加载字体文件,那么即使CSSOMDOM构建完成触发FP,页面内容也会是空白,只有等到字体文件下载完成才会出现内容(这也是我们在打开一个加载了谷歌字体的网站会白屏很长时间的原因)。
  • 默认情况下,CSS外链之间是谁先加载完成谁先解析,但是JS外链之间即使先加载完成,也得按顺序执行。
  • link外链后面紧跟script外链,须先等link parse完成之后,script才会执行,即使script先下载完成。script后面紧跟link,也是一样,会等script执行完之后,link才会parse
  • 如果script之后紧跟几个linkscript比这几个link的下载时间都长,那script执行完成之后link是按顺序执行。
  • RRDL
    • R:send Request,发送资源请求
    • R:receive Response,接收到服务端响应
    • D:receive Data,开始接受服务端数据(一个资源可能执行多次)
    • L:finish Loading,完成资源下载
  • 浏览器在RRDL的时候,在D(Receive data)这个步骤可能执行多次。
  • TTFB:Time To First Byte,第一个字节返回的时间,这个是对应send Requestreceive Response这段时间。
  • 浏览器会给HTML中的资源文件进行等级分类(Hightest/High/Meduim/Low/Lowest),一般HTML文档自身、head中的CSS都是Hightesthead中JS一般是High,而图片一般是Low,而设置了async/defer的脚本一般是Lowgif图片一般是Lowest
  • 下图中的资源文件浅色和深色和第二个图画红框的位置是对应的(不信自己计算一下对应的时间)

参考链接:

  1. 分析关键渲染路径性能
  2. CSS/JS对DOM渲染的影响
  3. CSS Animation性能优化
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-04-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
看了开头,似乎是我想了解的知识,先点个赞,下班再看!
看了开头,似乎是我想了解的知识,先点个赞,下班再看!
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
一次useEffect引发浏览器执行机制的思考
我相信大家首先想到的思路就是在useEffect中通过getBoundingClientRect()获得对应传入元素(id)的位置,然后通过定位增加一个类似的弹窗效果。
19组清风
2021/11/15
9920
一次useEffect引发浏览器执行机制的思考
探究网页资源究竟是如何阻塞浏览器加载的
一个页面允许加载的外部资源有很多,常见的有脚本、样式、字体、图片和视频等,对于这些外部资源究竟是如何影响整个页面的加载和渲染的呢?今天我们来一探究竟。
用户4456933
2021/06/01
2.2K0
探究网页资源究竟是如何阻塞浏览器加载的
css加载会造成阻塞吗
可能大家都知道,js执行会阻塞DOM树的解析和渲染,那么css加载会阻塞DOM树的解析和渲染吗?接下来,我就来对css加载对DOM树的解析和渲染的影响做一个测试。
嘿嘿嘿
2018/12/11
4.5K0
css加载会造成阻塞吗
浏览器加载解析渲染机制的全面解析
(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)
love丁酥酥
2018/08/27
1.2K0
浏览器加载解析渲染机制的全面解析
前端魔法堂:解秘FOUC
前言  对于问题多多的IE678,FOUC(flash of unstyled content)——浏览器样式闪烁是一个不可忽视的话题,但对于ever green的浏览器就不用理会了吗?下面尝试较全面地解密FOUC。 到底什么是FOUC?  页面加载解析时,页面以样式A渲染;当页面加载解析完成后,页面突然以样式B渲染,导致出现页面样式闪烁。  样式A,浏览器默认样式 或 浏览器默认样式 层叠 部分已加载的页面样式;  样式B,浏览器默认样式 叠加 全部页面样式。 为什么会出现FOUC  我们了解当输入网
^_^肥仔John
2018/01/18
1.5K0
浏览器渲染页面与DOM相关常见的面试题以及问题
  1.DOM Tree:浏览器将HTML解析成树形的数据结构,构建一颗DOM树,同时进行第三步。
用户10106350
2022/10/28
1.3K0
浏览器渲染页面与DOM相关常见的面试题以及问题
<script> 脚本以及 <link> 标签对 DOM 解析渲染的影响
当HTML解析器解析HTML,如果遇到script标签,普通的script标签会暂停对DOM解析渲染,因为该脚本可能会修改DOM。
不叫猫先生
2023/11/04
7020
<script> 脚本以及 <link> 标签对 DOM 解析渲染的影响
浏览器原理0. 前言1. 解析过程2. 渲染树2.1 CSS样式计算2.2 构建渲染树3. 布局(重要)4. 重绘与重排(重要)5. paint(绘制)6. composite(重要)7. 浏览器加载
身为前端,打交道最多的就是浏览器和node了,也是我们必须熟悉的。接下来我们讲一下浏览器工作原理和工作过程。从url到页面的过程,......,我们直接来到收到服务器返回内容部分开始。
lhyt
2018/10/31
5.4K0
前端-CSS与网络性能
在博客上,CSS 相关的文章却不多。那就结合 CSS 与性能这两大主题,为大家带来一篇文章吧。
grain先森
2019/03/29
1K0
前端-CSS与网络性能
前端资源浏览器渲染原理
当有了DOM Tree和 CSSOM Tree后,就可以两个结合来构建Render Tree了
冷环渊
2023/02/26
6000
前端资源浏览器渲染原理
JS 与 CSS 阻塞 DOM 渲染解析的情况详解
最近系统梳理HTML5所有涉及到的标签时,梳理至<link>和<script>标签时,碰巧想到一个困扰很久的问题,即一般把<script>放在<body>尾部,<link>标签放在<head>内部,而页面通过CDN引入第三方框架或库时,基本都是将其<script>标签放在<link>标签前面。
winty
2021/07/01
2.2K0
JS 与 CSS 阻塞 DOM 渲染解析的情况详解
HTML解析之DOMContentLoaded和onload
在很久很久以前,我在封装自己的JQuery库时就使用过DOMContentLoaded,觉得这个知识点看看别的文章就行了,不过现在我想把它记下来。
全栈程序员站长
2022/11/16
1.7K0
HTML解析之DOMContentLoaded和onload
HTML 渲染那些事儿
最近一段时间刚好在公司内部涉及一些老旧项目的优化,所以对于 Web 网页性能方面沉淀了一些自己的看法。
19组清风
2023/04/23
1.5K0
HTML 渲染那些事儿
前端不止:Web性能优化 - 关键渲染路径以及优化策略
我问你:“当你从搜索引擎的结果页面选择打开一条搜索结果时,你觉得多长时间之后,如果页面还处于白屏或者没有加载到关键信息,你会选择关掉这个窗口?”
ThoughtWorks
2018/07/23
1.1K0
前端不止:Web性能优化 - 关键渲染路径以及优化策略
网站性能优化(二)一定要将CSS置于顶部,JS置于底部吗?
“CSS文件在header中引入,JS文件在body底部引入”,这条建议在前端界几乎是黄金法则。
娜姐
2022/05/13
8970
网站性能优化(二)一定要将CSS置于顶部,JS置于底部吗?
浏览器渲染原理及流程
大多数设备的刷新频率是60Hz,也就说是浏览器对每一帧画面的渲染工作要在16ms内完成,超出这个时间,页面的渲染就会出现卡顿现象,影响用户体验。前端的用户体验给了前端直观的印象,因此对B/S架构的开发人员来说,熟悉浏览器的内部执行原理显得尤为重要。
前端迷
2019/08/29
4.7K0
浏览器渲染原理及流程
Web页面全链路性能优化指南
性能优化不单指优化一个页面的打开速度,在开发环境将一个项目的启动时间缩短使开发体验更好也属于性能优化,大文件上传时为其添加分片上传、断点续传也属于性能优化。在项目开发以及用户使用的过程中,能够让任何一个链路快一点,都可以被叫做性能优化。
唐志远
2023/08/01
7230
Web页面全链路性能优化指南
domReady的理解
domReady是名为DOMContentLoaded事件的别称,当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表、图像和子框架的完全加载。
WindRunnerMax
2020/09/24
1.1K0
最详尽的浏览器页面渲染机制分析
浏览器的内核是指支持浏览器运行的最核心的程序,分为两个部分的,一是渲染引擎,另一个是JS引擎。渲染引擎在不同的浏览器中也不是都相同的。目前市面上常见的浏览器内核可以分为这四种:Trident(IE)、Gecko(火狐)、Blink(Chrome、Opera)、Webkit(Safari)。这里面大家最耳熟能详的可能就是 Webkit 内核了,Webkit 内核是当下浏览器世界真正的霸主。本文我们就以 Webkit 为例,对现代浏览器的渲染过程进行一个深度的剖析。
挨踢小子部落阁
2019/12/04
1.7K0
文档解析和DOMContentLoaded触发时机
| 导语 大家都知道 HTML 文档完全加载和解析完成之后,会触发 DOMContentLoaded 事件,那么 HTML 里面的内容会如何影响文档解析呢?在解析过程中遇到 script 标签或者 link 标签时,解析会受影响吗?我们通过不同情况举例和 HTML5 规范一起分析一下。 DOMContentLoaded 触发定义 HTML 文档被完全加载和解析完成之后,会触发 DOMContentLoaded 事件,通常外部样式表和文档内的图片加载都不会影响该事件触发,不过也有特殊情况,我们后面会提到。 如
用户1097444
2022/06/29
8070
文档解析和DOMContentLoaded触发时机
推荐阅读
相关推荐
一次useEffect引发浏览器执行机制的思考
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验