Skip to main content

浏览器内核

对于浏览器的每个标签页都有属于自己的浏览器内核实例。而浏览器内核的主要功能是通过取得页面内容、整理信息(应用 CSS)、计算和组合最终输出可视化的图像结果,因此也被称为渲染引擎(渲染进程)。

浏览器内核划分:

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

GUI 渲染线程

  • 负责渲染浏览器界面,解析 HTML,CSS,构建 DOM 树、CSS 规则树以及渲染树,布局和绘制等。
  • 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行
  • GUI 渲染线程与 JS 引擎线程是互斥的,当 JS 引擎执行时 GUI 线程会被挂起(相当于被冻结了),GUI 更新会被保存在一个队列中等到 JS 引擎空闲时立即被执行。

JavaScript 引擎线程

Javascript 引擎,也可以称为 JS 内核,主要负责处理 Javascript 脚本程序,例如 V8 引擎。Javascript 引擎线程理所当然是负责解析 Javascript 脚本,运行代码

定时触发器线程

setInterval 与 setTimeout 所在线程,浏览器定时计数器并不是由 JavaScript 引擎计数的, 因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确, 因此通过单独线程来计时并触发定时是更为合理的方案。

事件触发线程

当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待 JS 引擎的处理。这些事件可以来自定时任务、也可来自浏览器内核的其他线程如鼠标点击、AJAX 异步请求等,但由于 JS 的单线程关系所有这些事件都得排队等待 JS 引擎处理。

异步 http 请求线程

在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果有回调函数,异步线程就产生状态变更时将事件放到 JavaScript 引擎的处理队列中等待处理。

GUI 渲染线程与 JS 引擎线程互斥

js 引擎线程在渲染的时候,很可能会执行一些 DOM 操作等,此时如果 GUI 渲染线程与 JS 引擎线程不互斥,那么当 JS 引擎执行一些 DOM 操作后会给 GUI 渲染线程的渲染带来迷惑,例如 GUI 渲染 id= ‘robbie’的 DOM 节点 div,此时 JS 线程却是要删除此节点,那么就会造成一种混乱,不知道该如何操作。为了渲染结果的一致性,GUI 渲染线程与 JS 引擎线程被设定是互斥的,当 JS 引擎执行时 GUI 线程会被挂起(相当于被冻结了),GUI 更新会被保存在一个队列中等到 JS 引擎空闲时立即被执行。

JS 的阻塞页面渲染

在默认情况下,js 的下载、解析和执行阶段都会阻塞页面的执行。由上面的内容可知 GUI 渲染线程与 JS 引擎线程互斥,所以在 JS 执行的时候,GUI 线程会被挂起。所以在代码中我们要尽量的将 JS 写在后面,等 DOM 执行完才执行。如果写在 DOM 树构建之前会加长白屏的时间。