浏览器的功能

        浏览器的主要功能就是向服务器发请求。然后展示我们所请求的网络资源。

浏览器的主要组成部分(7大模块)

用户界面(User Interface) :

除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。

浏览器引擎(Browser engine) :

        在用户界面和呈现渲染之间传送指令。在客户端本地缓存中读写数据等,是浏览器中各个部分之间相互通信的核心

渲染引擎(Rendering engine):

        负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。浏览器内核主要指的就是渲染引擎

网络(Networking):

        用来完成网络调用或资源下载的模块,比如 HTTP 请求。

用户界面后端(UI Backend):

        用来绘制基本的浏览器窗口内控件,如输入框、按钮、单选按钮等,根据浏览器不同绘制的视觉效果也不同,但功能都是一样的。

JavaScript 解释器(JavaScript Interpreter):

        用来解释执行JS脚本的模块,如 V8 引擎、JavaScriptCore

数据存储(Data Persistence):

这是持久层。浏览器需要在硬盘上保存 cookie、localStorage等各种数据,可通过浏览器引擎提供的API进行调用。这是一个完整(但是轻便)的浏览器内数据库。

浏览器架构 浏览器组成模块_HTML

渲染引擎 

渲染引擎,又称呈现引擎,也被称为浏览器内核,在线程方面又称为 UI 线程

渲染流程:

  • 获取数据:从网络层获取请求文档的内容。
  • 解析数据:解析 HTML 文档,并将各标记逐个转化成“内容树”上的 DOM 节点。同时也会解析外部 CSS 文件以及样式元素中的样式数据(cssom)。HTML 中这些带有视觉指令的样式信息(被赋予css样式的元素)将用于创建另一个树结构:呈现树(渲染数)(包含多个带有视觉属性(如颜色和尺寸)的矩形。这些矩形的排列顺序就是它们将在屏幕上显示的顺序。)
  • 布局:为每个节点分配一个应出现在屏幕上的确切坐标。
  • 绘制:渲染引擎会遍历呈现树,由用户界面后端层将每个节点绘制出来。

  JavaScript 解释器

         简单来说,JavaScript 解释器就是能够“读懂” JavaScript 代码,并准确地给出代码运行结果的一段程序。

所以 JavaScript 解释器,又称为 JavaScript 解析引擎,又称为 JavaScript 引擎,也可以成为 JavaScript 内核,在线程方面又称为 JavaScript 引擎线程比如 Chrome 的 V8 引擎。

浏览器多进程架构

        进程是 CPU 资源分配的最小单位
        线程是 CPU 调度的最小单位

进程:对于操作系统来说,一个任务就是一个进程,比如打开一个浏览器就是启动了一个浏览器进程,打开一个 Word 就启动了一个 Word 进程。

线程:在一个进程内部,要同时做多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程。

浏览器架构 浏览器组成模块_渲染引擎_02

 主进程 Browser Process:

        负责浏览器界面的显示与交互。各个页面的管理,创建和销毁其他进程。网络的资源管理、下载等。

第三方插件进程 Plugin Process

        每种类型的插件对应一个进程,仅当使用该插件时才创建。

渲染进程 Renderer Process

         称为浏览器渲染进程或浏览器内核,内部是多线程的。主要负责页面渲染,脚本执行,事件处理等。

渲染进程

        浏览器的渲染进程是多线程的

GUI (图形用户界面)渲染线程

        负责渲染浏览器界面,解析 HTML,CSS,构建 DOM 树和 RenderObject 树,布局和绘制等。

        当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。

        注意,GUI 渲染线程与 JS 引擎线程是互斥的,当 JS 引擎执行时 GUI 线程会被挂起(相当于被冻结了),GUI 更新会被保存在一个队列中等到 JS 引擎空闲时立即被执行

JS 引擎线程
        Javascript 引擎,也称为 JS 内核,负责处理 Javascript 脚本程序。(例如 V8 引擎)

        JS 引擎线程负责解析 Javascript 脚本,运行代码。

        JS 引擎一直等待着任务队列中任务的到来,然后加以处理,一个 Tab 页(renderer 进程)中无论什么时候都只有一个 JS 线程在运行 JS 程序。

注意,GUI 渲染线程与 JS 引擎线程是互斥的,所以如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。

事件触发线程
        归属于浏览器而不是 JS 引擎,用来控制事件循环(可以理解,JS 引擎自己都忙不过来,需要浏览器另开线程协助)

        当 JS 引擎执行代码块如 setTimeOut 时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX 异步请求等),会将对应任务添加到事件线程中

        当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待 JS 引擎的处理

注意,由于 JS 的单线程关系,所以这些待处理队列中的事件都得排队等待 JS 引擎处理(当 JS 引擎空闲时才会去执行)

定时触发器线程
        传说中的 setInterval 与 setTimeout 所在线程

        浏览器定时计数器并不是由 JavaScript 引擎计数的,(因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)

        因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待 JS 引擎空闲后执行)

注意,W3C 在 HTML 标准中规定,规定要求 setTimeout 中低于 4ms 的时间间隔算为 4ms。

异步 http 请求线程
        在 XMLHttpRequest 连接后是通过浏览器新开一个线程请求。

        将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中,再由 JavaScript 引擎执行。

通俗总结

        如果将浏览器比喻成汽车,那么浏览器的组成,相当于汽车的发动机轮胎,外壳,等一系列部件。而浏览器的进程可以理解为让汽车跑起来的一系列流程运动,如汽车主线程首先让油箱线程给他一滴油,然后主线程再将这底油给发动机线程,然后主线程将会得到相应物质,等等一些列的配合就使得汽车运动起来。