浏览器基础

329 阅读6分钟

作为一个菜鸡前端,天天Ctrl C V还是不太好,今天在网上总结一下浏览器的基础

浏览器的组成

浏览器简单来说浏览器可以分为两部分,shell+内核。其中shell的种类相对比较多,内核则比较少。 shell不多说,通俗来说就是花里胡哨的外壳,具体的来说咱也不知道。

作为前端我们需要了解一下内核,只是了解!

市场上浏览器种类繁多,好用的内核就那么几个:Trident(也称IE内核,辣鸡)、webkit(Safari内核,Chrome内核原型,开源)、Blink(现Chrome的)、Gecko(Firefox的)

内核又分成JS引擎和渲染引擎,JS引擎就是解析和执行JS的,最知名的应该就是Chrome的v8引擎,Safari的JavaScriptcore。

image.png

浏览器渲染引擎JS引擎
IEtridentchakra
Firefoxgeckospidermonkey
Chromeblinkv8
SafariwebkitJavaScriptcore
Operaprestocarakan

其实大家都以为webkit是Chrome的,实际上苹果才是webkit的鼻祖,现在的chromium内核是Blink和v8组成

前端页面的显示和运行离不开渲染引擎和JS引擎

  • 渲染引擎 -解析DOM文档和CSS规则并将内容排版到浏览器中显示有样式的界面,也有人称之为排版引擎,我们常说的浏览器内核主要指的就是渲染引擎
  • JS引擎 -用来解释执行JS脚本的模块,如 V8 引擎、JavaScriptCore

浏览器的进程和线程

什么是进程和线程

进程:
进程是系统中正在运行的一个程序,程序一旦运行就是进程。进程可以看成程序执行的一个实例,可以视作为浏览器打开了多个tab页,每个tab页相当于独立的进程。进程是系统资源分配的独立实体,每个进程都拥有独立的地址空间。一个进程无法访问另一个进程的变量和数据结构,如果想让一个进程访问另一个进程的资源,需要使用进程间通信,比如管道,文件,套接字等。

线程:
线程是进程的一个实体,是进程的一条执行路径。

线程是进程的一个特定执行路径。当一个线程修改了进程的资源,它的兄弟线程可以立即看到这种变化。 一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间。线程与进程的一个主要区别是,统一进程内的一个主要区别是,同一进程内的多个线程会共享部分状态,多个线程可以读写同一块内存(一个进程无法直接访问另一进程的内存)。同时,每个线程还拥有自己的寄存器和栈,其他线程可以读写这些栈内存。

这里以最常用的Chrome为例

image.png

在Chrome中,一般情况一个标签页就是一个单独进程,我们可以通过Chrome自带的任务管理器看到,扩展程序也都会占用一个进程;

这是因为不同进程不会出现数据共享,每个tab都有自己的独立渲染引擎实例,因此每个标签单独使用一个进程更安全、合理;不过由一个标签打开的另个标签并且属于同域名下被认为是高度相关的,会被归为一个进程

在浏览器内核的控制下,一般有5个常驻线程

线程解释说明
GUI 渲染线程GUI渲染线程负责渲染浏览器界面HTML元素,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。在Javascript引擎运行脚本期间,GUI渲染线程都是处于挂起状态的,也就是说被冻结了.
JavaScript引擎线程JS为处理页面中用户的交互,以及操作DOM树、CSS样式树来给用户呈现一份动态而丰富的交互体验和服务器逻辑的交互处理。如果JS是多线程的方式来操作这些UI DOM,则可能出现UI操作的冲突;如果JS是多线程的话,在多线程的交互下,处于UI中的DOM节点就可能成为一个临界资源,假设存在两个线程同时操作一个DOM,一个负责修改一个负责删除,那么这个时候就需要浏览器来裁决如何生效哪个线程的执行结果,当然我们可以通过锁来解决上面的问题。但为了避免因为引入了锁而带来更大的复杂性,JS在最初就选择了单线程执行。GUI渲染线程与JS引擎线程互斥的,是由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JavaScript线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致。当JavaScript引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到引擎线程空闲时立即被执行。由于GUI渲染线程与JS执行线程是互斥的关系,当浏览器在执行JS程序的时候,GUI渲染线程会被保存在一个队列中,直到JS程序执行完成,才会接着执行。因此如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
定时触发器线程浏览器定时计数器并不是由JS引擎计数的, 因为JS引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确, 因此通过单独线程来计时并触发定时是更为合理的方案。
事件触发线程当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可以是当前执行的代码块如定时任务、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。
异步http请求线程在XMLHttpRequest在连接后是通过浏览器新开一个线程请求,将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到JS引擎的处理队列中等待处理。

浏览器渲染页面的流程

浏览器工作流程

1、浏览器先解析3个东西

  • HTML/SVG/XHTML,浏览器解析这三种文件生成DOM tree
  • CSS 被浏览器解析生成 CSS Rule Tree
  • JavaScript 通过DOM API 和CSSOM API操作DOM Tree 和CSS Rule Tree

2、解析原始文件后通过DOM Tree和CSS Rule Tree生成一个Rendering Tree

  • Rendering Tree 不同于 DOM tree ,比如header标签和display:none;的标签不会被解析到Rendering Tree中
  • CSS Rule Tree把每个CSS rule匹配并附加的Rendering Tree上的对应的Element(也就是DOM节点,亦称Frame)
  • 计算每个Element(亦称Frame)的位置,这个叫layoutpaint过程

image.png