在分析浏览器渲染过程之前,我们先了解进程和线程:

  • 什么是进程?
    进程是CPU进行资源分配的最小单位
  • 什么是线程?
    线程是CPU调度的最小单位,是建立在进程的基础上的运行单位,共享进程的内存空间,通俗点解释线程就是程序中的一个执行流,一个进程可以有多个线程

那么我们可以得出结论:进程会占用系统资源,在一个进程内可以存在一个或多个线程,这就是单线程和多线程,但是无论是单线程还是多线程,都是在一个进程内。

JS为什么是单线程?

JS的单线程,与它的用途有关,作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM,这决定了它只能是单线程,否则会带来很复杂的同步问题
比如,假定 JavaScript 同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

浏览器的多进程

浏览器是多进程的,不同类型的标签页都会开启一个新进程,相同类型的标签页会合并成一个进程。

浏览器各个进程的主要作用如下:

  • 浏览器进程 (主进程,该进程只有一个)
    1.负责各个标签页的管理,创建和销毁其他进程
    2.负责浏览器界面显示,与用户交互。如前进,后退等
    3.负责网络资源的管理与下载
  • 第三方插件进程
    每种类型的插件对应一个进程,当使用该插件时才创建
  • GPU进程
    该进程也只有一个,负责3D/动画绘制和硬件加速
  • 浏览器渲染进程
    1.即通常所说的浏览器内核(Renderer进程,内部是多线程)
    2.每个Tab页面都有一个渲染进程,互不影响
    3.主要负责页面渲染,脚本执行,事件处理等

浏览器内核

浏览器内核就是浏览器渲染进程,从接收下载文件后再到呈现整个页面的过程,由浏览器渲染进程负责,主要的流程如下:

1.解析HTML文件和CSS文件,加载图片等资源文件,渲染成用户看到的页面。
2.执行解析js文件脚本代码。

在该过程中浏览器渲染进程会开启多个线程协作完成,主要的线程以及作用如下:

  • GUI渲染线程
  • js引擎线程
  • 事件触发线程
  • 异步http请求线程
  • 定时器线程

注:GUI渲染线程与JS引擎线程是互斥的,因为JS引擎线程在执行过程中可能会发生重绘和回流,所以GUI渲染线程执行时候,JS引擎线程会被挂起,等待GUI渲染线程执行完毕才会执行;JS引擎线程执行时候同理。

渲染主流程

GUI渲染线程渲染的过程主要分为下面几步(以Chrome为例):

  1. 解析获取到的HTML文档,构建DOM树,同时浏览器主进程负责下载。
  2. CSS文件下载完成,解析CSS文件,构成层叠样式表模型CSSOM(CSS Object Model)的CSS规则树。然后结合DOM树合并成RenderObject树
  3. 将DOM树和CSSOM合并为渲染树(Rendering tree)。
  4. 有了Rendering Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系,从而去计算出每个节点在屏幕中的位置,它被称之为布局layout。浏览器使用一种流式处理的方法布局。
  5. 按照算出来的规则,通过显卡,将渲染树的各个节点绘制到屏幕的像素信息,这一步被称为绘制painting。
  6. 再接下来是我们这最后一步合成( composite ),浏览器主进程将默认图层和复合图层交给GPU进程,GPU进程再将各个图层合成,最后显示出页面.

术语解释:
默认图层: 默认图层大家就可以理解为普通文档流,因为里面不管添加多少元素,其实都是在同一个图层中,absolute 布局、 fixed 也一样,虽然可以脱离普通文档流,但它仍然属于 默认图层。
复合图层:可以独立于普通文档流中,改动后可以避免默认图层的重绘和回流,提升性能,但也不要大量使用复合图层,否则由于资源消耗过度,页面反而会变的更卡,因小失大,最常用的方式是 transform 或者<canvas><webgl>等元素。

Webkit的渲染流程图如下所示:


注意:

  • Render Tree和DOM Tree不完全对应。

  • DOM中不可见标签元素不会放到渲染树中,就像<head></head> 或 display:none

  • visibility: hidden的元素在渲染树中

了解GUI渲染线程的执行过程后,我们可以根据其渲染原理进行渲染优化:

  • 尽可能提前引入css文件,例如在头部引入css文件。
  • 简化并优化CSS选择器,尽量将嵌套层减少到最小。
  • 尽可能早加载css文件中引用的资源,例如自定义字体文件,可以使用预加载,在link标签加入’rel=”preload” as=”font”‘该元素属性,不然会造成渲染阻塞。
  • 在DOM和CSS渲染之后加载js文件,例如在尾部加载js文件,或者使用该元素属性”defer”和”async”,进行js文件异步加载,但是在不同浏览器会有兼容性问题。

回流和重绘(reflow和repaint)

说到资源的阻塞我们清楚的是,现代浏览器总是并行加载自语言。例如当HTML解析器被脚本阻塞时,解析器虽然会停止构建DOM,但仍然会辨识该脚本后面的资源,并进行预加载。且由于以下两点。浏览器会延迟 JavaScript 的执行和 DOM 构建:

  • reflow(回流)
    当浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,内行称这个回退的过程叫 reflow。reflow 会从 这个 root frame 开始递归往下,依次计算所有的结点几何尺寸和位置。reflow 几乎是无法避免的。现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显 示与隐藏)等,都将引起浏览器的 reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引起它内部、周围甚至整个页面的重新渲 染。通常我们都无法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。
  • repaint(重绘)
    改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变。

注意:

  1. display:none 的节点不会被加入Render Tree,而visibility: hidden 则会,所以,如果某个节点最开始是不显示的,设为display:none是更优的。
  2. display:none 会触发 reflow,而 visibility:hidden 只会触发 repaint,因为没有发现位置变化。
  3. 有些情况下,比如修改了元素的样式,浏览器并不会立刻reflow 或 repaint 一次,而是会把这样的操作积攒一批,然后做一次 reflow,这又叫异步 reflow 或增量异步 reflow。但是在有些情况下,比如resize 窗口,改变了页面默认的字体等。对于这些操作,浏览器会马上进行 reflow。

如何减少和避免回流重绘

回流开销太大了,那么我们肯定是要优化的:

  • 减少逐项更改样式,最好一次性更改 style,或者将样式定义为 class 并一次性更新
  • 避免循环操作DOM,让DOM离线后再修改
    1.创建一个 documentFragment ,在它上面应用所有DOM操作,最后再把它添加到 window.document
    2.先把DOM节点 display:none ( 会触发一次 reflow),然后做修改后,再把它显示出来
    3.克隆一个DOM节点在内存里,修改之后,与在线的节点相替换
  • 避免多次读取offset等属性,无法避免则将它们缓存到变量
  • 将复杂的元素绝对定位或固定定位,使得它脱离文档流,否则回流代价会很高
  • 改变字体大小也会引发回流,所以尽可能减少这种操作
  • table布局,一个小改动会造成整个table的重新布局,所以,少用为好

总之,说来说去,回流重绘,特别是回流,特别耗费资源,尽量避免就好

必考面试题:浏览器怎么渲染页面的相关推荐

  1. 2018 BAT最新《前端必考面试题》

    2018 BAT最新<前端必考面试题> 1.Doctype作用? 严格模式与混杂模式如何区分?它们有何意义? (1). 声明位于文档中的最前面,处于 标签之前.告知浏览器的解析器,用什么文 ...

  2. (一)梳理前端知识体系,搞定大厂必考面试题

    梳理前端知识体系,搞定大厂必考面试题 常见面试题 JS基础知识 变量类型和计算 原型和原型链 作用域和闭包 异步和单线程 运行环境 HTTP协议 总结 常见面试题 JS基础知识 变量类型和计算 typ ...

  3. java comparator_【面试题】Java必考面试题全集(15)

    Java基础面试题(15) 1:Comparator 与Comparable 有什么不同? 2:Object中有哪些方法? 3:说下jdk8中的一些新特性 4:在64 位 JVM 中,int 的长度是 ...

  4. Vue是如何渲染页面的,渲染过程以及原理代码

    Vue是如何渲染页面的,渲染过程以及原理代码:https://www.cnblogs.com/ypinchina/p/7238402.html 转载于:https://www.cnblogs.com/ ...

  5. 金九银十专供 | 175 道 Go 工程师必考面试题 + 详细解答

    随着云计算时代的到来,Go 的应用越来越广泛,已然成为首选编程语言,而且,薪资也水涨船高. 以字节跳动为例,Go 语言是字节跳动内部使用最多的编程语言.为啥?因为字节跳动更看重效率,上手简单,学习难度 ...

  6. 浏览器是如何渲染页面的?

    渲染的流程如下: 1.解析HTML文件,创建DOM树. 自上而下,遇到任何样式(link.style)与脚本(script)都会阻塞(外部样式不阻塞后续外部脚本的加载). 2.解析CSS. 优先级:浏 ...

  7. 阿里菜鸟二面:高级java面试题和答案!含阿里必考面试题赠送!

    阿里菜鸟一面面试题目: 1.你比较了解的机器学习的算法有哪些,说一下这些算法的过程和区别 2.网络的体系结构分为哪五层,每层分别有哪些协议 3.TCP和UDP的区别是什么,如果想发送即时消息应该用哪种 ...

  8. 机器学习面试必考面试题汇总—附解析

    问题:xgboost对特征缺失敏感吗,对缺失值做了什么操作,存在什么问题 不敏感,可以自动处理,处理方式是将missing值分别加入左节点 右节点取分裂增益最大的节点将missing样本分裂进这个节点 ...

  9. c语言必考面试题,c语言面试最必考的十道试题,求职必看!!!

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 6.free()函数 问:下面的程序会在用户输入'freeze'的时候出问题,而'zebra'则不会,为什么? #include int main(int ...

最新文章

  1. android上的i-jetty (1)环境搭建
  2. ESP32的FLASH、NVS、SPIFFS、OTA等存储分布以及启动过程
  3. Spring 天天用,bean 懒加载原理你懂吗?
  4. 怎么给国外的客户开Invoice?
  5. JVM内存分为哪几部分?各个部分的作用是什么?
  6. hadoop学习3 查找块的位置
  7. Java 并发编程之 CopyOnWriteArrayList
  8. Unity 官方教程 学习
  9. No space left on device 磁盘空间提示不足解决办法
  10. centos mysql无法启动 sock_CentOS通过yum安装MariaDB(MySQL)无法启动服务或者找不到mysql.sock...
  11. linux下的raid及mdadm的命令详解
  12. 使用微PE制作启动U盘重装系统教程
  13. 使用git上传代码遇到关于remote: Support for password authentication was removed on August 13, 2021.的问题
  14. [javascript|基本概念|Underfined]学习笔记
  15. 机器学习第三课--LWR的疑惑与想法
  16. Python实现头条自动发文章,赚点广告费!
  17. java源码 - SpringMVC(9)之 其他Resolver
  18. python适合做游戏的背景音乐是什么_适合做游戏的背景音乐
  19. 自上而下的因果关系:数学结构与观察者
  20. istio-jaeger部署

热门文章

  1. Html调用手机打电话功能
  2. 开通OSChina的感概
  3. 英文歌曲:my heart will go on(我心永恒)
  4. android投影到创维电视,安卓手机投屏到电视的3个方法,赶紧收藏!
  5. 《Flutter 控件大全》第五十五个:InkWell和Ink
  6. 使用python完成知乎模拟登陆
  7. 设计师必备的三个导航网站
  8. IO多路复用底层原理及源码解析
  9. 蓝牙芯片----BK3431开发笔记------RW stack中添加自定义服务教程(4)
  10. 微商分销功能不能用了