浏览器内核及工作原理

672 阅读9分钟

PgPX6ZMyKSwF6kB8zIhB.png

一般浏览器由浏览器引擎(Browser Engine)、JavaScript解释器(JavaScript Interpreter)、用户界面(User Interface)、网络化(Networking)、UI后端(UI backend)、数据存储(Data Storage)等组件组成。

浏览器内核

主流浏览器主要有Google Chrome、Microsoft Edge、Apple Safari、Mozilla Firefox、Opera等。IE逐渐退出历史舞台,但目前国内主流浏览器都是双内核浏览器,仍保留着它的神话。

浏览器内核(Rendering Engine),是指浏览器最核心的部分,负责对网页语法的解释(如标准通用标记语言下的一个应用HTML、JavaScript)并渲染(显示)网页。

通常所谓的浏览器内核也就是浏览器所采用的渲染引擎。

浏览器引擎(browser engine),也称为排版引擎(layout engine)、页面渲染引擎(rendering engine)或样版引擎,它是一种软件组件,负责获取标记式内容(如HTML、XML及图像文件等等)、整理信息(如CSS及XSL等),并将排版后的内容输出至显示器或打印机。

常见的浏览器的内核:

  • Webkit:KDE的KHTML及KJS函式库的一个分支,被使用在Safari、Google Chrome、Opera。(Chrome仅仅使用WebCore,而JavaScript引擎及多任务系统则自行开发。)
  • Blink:开源引擎WebKit中WebCore组件的一个分支,在Chrome(28及往后版本)、Opera(15及往后版本)、Edge(79及往后版本)等基于Chromium的浏览器中使用。
  • Gecko:由网景通信公司开发,现在则由Mozilla基金会维护,使用于Netscape 6、Firefox(Servo引擎处于发展阶段)。
  • Trident:Internet Explorer的排版引擎,在Edge浏览器中被其分支EdgeHTML所取代。(微软还有另一个Tasman引擎。)
  • Presto:由Opera Software开发的网页浏览器排版引擎,取代了旧版Opera 4至6版本使用的Elektra排版引擎,由Opera 7.0至12.18版本所使用。

JavaScript引擎

JavaScript引擎是一个专门处理JavaScript脚本的虚拟机,一般会附带在网页浏览器之中。

主流浏览器的JavaScript引擎:

  • SquirrelFish:重写JavaScriptCore,由字节码解释器演变成Nitro,可将JavaScript编译为机器语言而不再需要解释器,加速JavaScript的执行。
  • V8:由Google开发的开源JavaScript引擎,用于Google Chrome及Chromium中,项目以V8发动机其命名。
  • SpiderMonkey:第一个JavaScript引擎,由布兰登·艾克在网景公司开发,用于Netscape Navigator网页浏览器中,目前为Firefox所使用。
  • Chakra:由微软为其Internet Explorer 9和Internet Explorer 10和Internet Explorer 11和等网页浏览器开发的JScript引擎。
  • Carakan:Opera推出的JavaScript引擎,拥有基于寄存器的字节码,机器语言生成,自动对象分类及整体性能改进。

浏览器工作原理

从输入URL到浏览器显示页面的过程中都发生了什么?

解析URL

URL是因特网上标准的资源的地址(Address),包括以下元素:

  1. 传送协议
  2. 层级URL标记符号(为“//”,固定不变)
  3. 访问资源需要的凭证信息(可省略)
  4. 服务器(通常为域名,有时为IP地址)
  5. 端口号(以数字方式表示,若为默认值可省略)
  6. 路径(以“/”字符区别路径中的每一个目录名称)
  7. 查询(GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与资料,通常以UTF-8的URL编码,避开字符冲突的问题)
  8. 片段(以“#”字符为起点)

标准格式如下:

[协议类型]://[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]

完整格式如下:

[协议类型]://[访问资源需要的凭证信息]@[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]

DNS解析

DNS是互联网的一项服务,作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。浏览器根据URL解析结果,进行DNS解析,获得IP地址:

  1. 从浏览器缓存中查询
  2. 从操作系统缓存中查询
  3. 从路由器中查询DNS缓存
  4. 从ISP中查询DNS缓存
  5. 域名服务器迭代查询,根据返回的地址逐级向上查询

TCP连接

TCP-connection-1.png

获得目标服务器IP地址后,浏览器会和服务器建立TCP连接。建立TCP连接的过程包括“三次握手”:

  1. 客户端向服务器发送一个SYN报文段,报文段的首部中的标志位SYN置为1,另外还会指明自己的初始化序号seq=x,此时客户端处于SYN_SENT状态。
  2. 服务器收到SYN的报文段后,会以自己的SYN-ACK报文进行应答。该应答报文的首部有三个重要信息:首先SYN被置为1;其次,确认号字段ack=x+1;最后服务器选择自己的初始序号seq=y。该报文段表明:“我收到了你发起建立连接的请求,该请求报文的初始序号是x(确认号ack=x+1就表明了我收到了初始序号seq=x的报文),我同意建立该连接,我的初始序号是y。”此时服务器处于SYN_RCVD状态。
  3. 客户端收到SYN-ACK报文后,会发送一个ACK报文段,该报文段中序号seq=x+1,确认号ack=y+1,表明我已经收到了你的确认。此时客户端处于ESTABLISHED状态。

服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方建立起了连接。

发送HTTP请求

建立TCP连接后,浏览器会向服务器发送HTTP请求。HTTP(Hyper Text Transfer Protocol)是一种应用层协议,它定义了客户端和服务器之间的通信格式。

HTTP请求包括:请求方法、URL路径、HTTP版本号、请求头部信息和请求正文。其中,请求方法常见的有GET、POST等。

服务器处理请求并返回响应

收到HTTP请求后,服务器会根据请求内容进行相应的处理,并生成HTTP响应。HTTP响应也包含HTTP版本号、状态码、响应头部信息和响应正文。HTTP状态码有很多种,常见的有:

  • 200 OK:表示请求成功。
  • 301 Moved Permanently:表示请求的资源已经永久移动到新位置。
  • 404 Not Found:表示请求的资源不存在。
  • 500 Internal Server Error:表示服务器内部错误。

浏览器解析渲染

浏览器一边加载HTML文档,一边开始解析。

  1. 当解析到<script>就会暂停,渲染引擎将控制权交给JavaScript引擎。如果引用了外部脚本就下载,否则就执行代码。JavaScript引擎执行完毕,控制权交还渲染引擎,恢复解析HTML。
    • 当发现带有defer属性的<script>,浏览器继续解析HTML,同时并行下载<script>加载的资源。浏览器完成HTML解析,然后执行下载的脚本。
    • 当发现带有async属性的<script>,浏览器继续解析HTML,同时并行下载<script>加载的资源。脚本下载完成,浏览器暂停解析,开始执行下载的脚本。脚本执行完毕,浏览器继续解析。
    • 当解析和执行CSS也会阻塞:Firefox会等到脚本前面的所有样式表,都下载并解析完再执行脚本;Webkit发现脚本引用了样式就会暂停执,等到样式表下载并解析完再恢复执行。
  2. 当解析到图片、CSS、视频等其他资源,则调用资源加载器进行异步加载,不阻碍DOM树的构建。

浏览器渲染原理

bPlYx9xODQH4X1KuUNpc.png

S9TJhnMX1cu1vrYuQRqM.png
  1. 解析代码:HTML代码解析为DOM,CSS代码解析为CSSOM。
    • 解析HTML
      • 将数据的原始字节(Bytes)转换为字符(Characters)。
      • 字符进一步解析为标记(Tokens)。
      • 标记化完成后,令牌将转换为节点(Nodes)。
      • 节点将加到数据结构(Object Model)。
    • 解析CSS
      • 当收到CSS原始字节时,也会启动HTML的类似过程。
  2. 合并渲染树(Render Tree)。
    • CSSOM在DOM构建完成之后,将解释的样式信息附加到DOM上。
    • DOM创建的同时也会创建渲染对象(RenderObject)。
    • 可感知的DOM和CSSOM合并成渲染树。
  3. 计算出渲染树的布局(Layout)。
    • 渲染树建立之后,布局运算会计算出样式布局信息。
    • 根据层叠上下文对渲染对象进行分层,并创建渲染层(RenderLayer)。
    • 如果开启硬件加速则会创建图形层(GraphicsLayer)。
    • 每个渲染层附带生成绘制命令的上下文信息。
  4. 绘制(Paint)渲染树到屏幕。
    • 渲染引擎将渲染层分块为小的区域进行光栅化。
    • 光栅化的位图经过计算生成指引信息,最终呈现至屏幕。

重绘与重排

渲染树转换为网页布局,称为“布局流”(flow);布局显示到页面的这个过程,称为“绘制”(paint)。它们都具有阻塞效应,并且会耗费很多时间和计算资源。

当浏览器重新计算网页的某些部分的位置和几何形状时,例如在交互式网站上更新之后,会发生回流(reflow);当浏览器重绘网页以显示UI更改导致的视觉更新时(例如在交互式站点上更新后),就会发生重绘(repaint)。

重排和重绘并不一定一起发生,重排必然导致重绘,重绘不一定需要重排。比如改变元素颜色,只会导致重绘,而不会导致重排;改变元素的布局,则会导致重绘和重排。

关闭TCP连接

TCP-close-diagram.png

四次挥手也就是客户端与服务器断开连接时,需要一共发送四个报文段来完成断开TCP连接。

  1. 客户端发送一个FIN报文段,报文段中指定序号seq=u。此时客户端处于FIN_WAIT_1状态。
  2. 服务器收到FIN报文后,立即发送一个ACK报文段,确认号为ack=u+1,序号设为seq=v。表明已经收到了客户端的报文。此时服务器处于CLOSE_WAIT状态。在第二次挥手和第三次挥手之间的时间段内,由于只是半关闭的状态,数据还是可以从服务器传送到客户端的。
  3. 如果数据传送完毕,服务器也想断开连接,那么就发送一个FIN报文,并重新指定一个序号seq=w,确认号还是ack=u+1,表明可以断开连接。
  4. 客户端收到报文后,一样发出一个ACK报文段做出应答,上一次客户端发送的报文段序号为u,那么这次序号就是seq=u+1,确认号为ack=w+1。此时客户端处于TIME_WAIT状态,需要经过一段时间确保服务器收到自己的应答报文后,才会进入CLOSED状态。

服务器收到ACK报文后,就关闭连接,也处于CLOSED状态了。