浏览器内核及渲染机制

浏览器内核及渲染机制


前言

浏览器内核可以说是整个网页的重中之重了,整个网页的资源解析、脚本执行、界面渲染、事件处理等,都需要依靠浏览器的内核来执行。本篇文章我们就通过浏览器的进程和线程入手,再到具体的渲染过程。


一、进程与线程?

进程是操作系统分配资源的最小单位,线程是程序执行的最小单位,一个进程里的多个线程可以共享进程里的资源。
这句话,相比对于学计算机的小伙伴都耳熟能详了。
进程就相当于计算机分配给一个程序实例的内存空间,可以理解为一个上下文(环境),在这个环境中,所有线程的资源是互相共享的。而多线程就相当于一个进程里有多个执行流,可以同时执行不同的任务互不干扰,并且共享同一块进程的资源。

1.浏览器进程

很多小伙伴可能误认为浏览器是单进程的,事实上浏览器在背后处理复杂的逻辑,单靠一个进程肯定是不够的,需要多个进程来一起共同协作。试想一下,如果浏览器只有一个进程,运行期间一个tab页面突然异常错误了,那么整个浏览器势必就会crash(宕机)。并且多个tab页面在一个进程里运行,共享一个进程的资源,肯定是不安全的。因此,要采用多进程的模式。
浏览器主要有以下几个进程:

  1. Browser进程:浏览器的主控进程。
  2. 插件进程:每种类型的插件创建一个进程。
  3. GPU进程:最多一个,用于3d绘制等。
  4. 渲染进程(浏览器内核):每开一个tab页面就会新开一个渲染进程。

2.浏览器线程

浏览器是多线程的。这里我们主要讲内核里面的线程。

其中我们常说的内核(Rendering Engine),也叫“渲染引擎”,是网页呈现最重要的核心。(原先的内核说的是渲染引擎+js引擎,后来随着js引擎独立开来,现在说内核一般是渲染引擎)它决定了网页如何显示页面以及页面的格式信息等。因此你可以把渲染引擎想象成一个浏览器厂商封装好的黑盒,里面有负责不同功能的模块。相关资源文件流经黑盒,经过解析、处理、渲染等操作最终输出一个页面

在这里插入图片描述

ps:常见主流浏览器内核
1、IE浏览器内核:Trident内核,也是俗称的IE内核;
2、Chrome浏览器内核:统称为Chromium内核或Chrome内核,以前是Webkit内核,现在是Blink内核;
3、Firefox浏览器内核:Gecko内核,俗称Firefox内核;
4、Safari浏览器内核:Webkit内核;
5、Opera浏览器内核:最初是自己的Presto内核,后来是Webkit,现在是Blink内核。

而渲染引擎,就对应着我们上面所说的渲染进程。

渲染进程包含的线程主要有以下五个:
1)GUI渲染线程
负责渲染浏览器界面,解析HTML,CSS,构建DOM树和Render树,进行布局和绘制等。当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。
注意:GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(即常说的资源阻塞),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。

2)JS引擎线程
也称JS内核,主要负责JS脚本的解析和执行(如V8引擎)。JS引擎是单线程的,执行流自上而下执行脚本的同步代码,同时它还维护着两个异步队列,一旦主线程空闲时,就会轮循抓取队列中的代码来执行。
所以一个tab页(renderer进程)中有且仅有一个JS线程在执行,JS单线程在之后会详细说到。

3)事件触发线程
归属于浏览器而不是JS引擎,用来控制事件循环。
当一个事件(定时器、点击事件、异步请求)符合触发条件被触发时,该线程会把事件对应的回调函数(任务)添加到待处理队列的队尾,等待JS引擎的处理。

4)定时触发器线程
setInterval与setTimeout所在线程。
浏览器定时计数器并不是由JavaScript引擎计数的,需要另一个线程单独计数,毕竟单线程的JS来进行计时的话,会造成不必要的阻塞。
同样计时完毕后,将对应的回调函数(任务)添加到任务队列中,等待JS引擎空闲后抓取执行。
ps:W3C中规定,setTimeout中低于4ms的时间间隔算为4ms(也就是0ms也算4ms)。

5)异步http请求线程
一般通过实例化一个XMLHttpRequest后,浏览器就会新开一个请求线程。通过该线程去建立链接、发起请求,监听请求的状态并将相应的回调放入任务队列中,由JS引擎抓取执行。

二、页面渲染过程

浏览器拿到从后端返回的资源后,如HTML/CSS/JS,是如何解析这些资源并渲染生成页面的呢?其中主要有以下几个步骤:

  • 解析HTML构建DOM树,解析CSS构建CSSOM(也叫css rule tree)
  • 将DOM树和CSSOM合并成渲染树(render tree)
  • 布局,计算各个元素的位置等几何信息
  • 绘制
  • 合并图层
    在这里插入图片描述

1.解析html和css

  • 浏览器拿到html文件后,首先解析html文件构建dom树。html文档中,一切皆为节点,常见的几种节点有:文档节点、元素节点、文本节点、属性节点、注释节点。DOM节点树中节点与HTML文档中的标签内容一一对应。dom树的构建是一个深度遍历的过程,只有当前节点的子节点构建好后,才会去构建当前节点的下一个兄弟节点。
  • 此时如果遇到外部css文件(通过link标签引入),图片等其他资源(不包含JS),浏览器会去请求并加载。并且解析css和解析html可以同时进行,它不阻塞html的加载解析,只阻塞dom的渲染(关于各个资源的阻塞后面再细谈)。解析完成后构建为CSSOM树。

DOM和CSSOM的构建流程:
读取html/css文档,将字节转换成字符,确定tokens(标签),再将tokens转化为节点,以节点来构建树。

2.构建渲染树

在第一步解析完拿到dom树和cssom树后,渲染引擎会给dom树的每个节点附加上样式结构体,即cssom中对应的节点。这样一来就形成了带有样式信息的节点树,也就是渲染树。并且这个过程中会丢弃那些不用呈现在页面的节点,譬如meta标签、script标签以及display为none的节点。因此渲染树和dom树不是一一对应的,一些dom节点在合并渲染树的过程中会被过滤掉。

构建渲染树不是说等待dom树和cssom树构建完毕后才能进行,实际上并无先后之分,浏览器对资源的加载、解析、渲染是并行交错的。所以会有一边加载、一边解析、一边渲染的情况。因此只要解析完一部分html和css,它就会着手构建渲染树。

3.布局和绘制

布局,又称Layout。渲染引擎根据render-tree的各个节点来计算布局信息,比如各个box的位置和尺寸。然后通过遍历render-tree的各个节点,利用浏览器的UI层进行绘制,将带有样式信息的节点转化为屏幕上的绝对像素,合并各个图层形成最终的页面。

回流和重绘:
回流(reflow),当页面中某个部分的变化影响了布局,需要倒回去重新layout,重新渲染,这个过程就叫回流。渲染引擎在第一次渲染页面的时候一定会发生回流。而在之后通过,页面的交互、css的改变等,譬如点击、输入表单、缩放窗口等,只要引起页面上元素占位面积、边距、定位方式等的变化,都会引起它内部、周围甚至整个页面的重新渲染。
重绘(repain),当改变某个元素的颜色、背景等不影响它周围布局的属性时,页面的一部分要重新绘制。
回流一定会引起重绘,而重绘不一定能够引发回流。

三、资源的阻塞?

上面讲了渲染引擎输出页面的大体渲染过程。在渲染的过程中资源是会产生阻塞的,如果没有阻塞将会出现一些意想不到的情况,下面我们就来谈谈其中的阻塞。

  1. html的阻塞,html阻塞是一定的,没有最基本的dom节点就渲染不出页面。
  2. css阻塞,上面提到过,css解析和html解析是可以并行的,但是对于渲染来说,浏览器是不会在cssom没有构建好时渲染页面的,即使dom解析完,也要等待cssom构建。这样是为了避免丑陋的页面直接展示在用户面前。因此css样式一般放在页面头部是最好的,这样能让它尽快解析,方便更快地将页面呈现给用户。
  3. js阻塞,js的解析和执行是由独立的js引擎来执行的。对于dom和cssom的构建来说,js脚本会对他们产生阻塞。**因为js可以操作页面的节点和样式,如果两者能同时进行,势必会造成紊乱。**因此浏览器在构建dom和cssom时遇到js脚本的话,会先停止渲染,将控制权交给js引擎。等到脚本执行完毕,才会继续dom和cssom的构建(需要注意的是,解析器虽然停止构建dom和cssom,但仍会识别后续的资源并进行预加载)。因此,脚本一般放在页面的底部,遵循“先呈现页面给用户”的原则,对于交互可以之后再附加上去。

js脚本的不同处理方式:

  1. 默认:阻塞资源
  2. async:普通的异步模式,异步加载js脚本,但加载完后立即执行
  3. defer:延迟执行,异步加载js,加载完成后不执行,等到html和css解析完后才执行

对于影响对页面元素和样式较多的脚本,可以利用defer来实现。而对于普通的脚本我们可以使用async或者将脚本放在页面底部。

总结

浏览器的渲染是一个十分复杂的过程。从用户输入一个url到最终输出一个页面,中间要经过许多浏览器底层模块的调度和协作。本文只是讲解了只关于渲染的那部分,即浏览器的内核(渲染进程),后续还会继续研究浏览器其他层面的运作。另外有一点需要注意的是,在页面元素较多较复杂时,浏览器一般会先渲染一部分页面,再渐进地加载渲染其他部分直至整个页面呈现完毕

参考链接:https://www.cnblogs.com/lianchenxi/p/10129620.html
再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载
https://blog.csdn.net/qq_39669807/article/details/89388014

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值