浏览器的渲染原理

引言

在我们的日常生活中,互联网已经不可或缺。而游览器,就像是我们浏览这个数字世界的窗口,成为我们与互联网交流的必备工具。有时候,你是否被一些页面无法正确显示,或者响应缓慢等情况困扰过?这就需要我们理解浏览器的“大脑”——内核,及其如何将代码渲染为我们看到的页面。然而浏览器内核的原理和渲染的机制对于许多人来说可能还是一个未知领域。今天我们就聚焦这个看似晦涩但却影响我们每时每刻上网体验的内核以及浏览器的渲染原理。

一、什么是浏览器

浏览器,全称网页浏览器,是一种软件应用程序它翻译HTTP或HTTPS的指令来生成用户可以看到的页面,用户通过它在Internet上导航或浏览信息。信息可能是网页、图片、视频或其他类型的网页内容。浏览器让我们可以连接到Web服务器,下载网页和其他数据到计算机或移动设备,并将这些信息呈现给用户。

浏览器并非只能截取和浏览Internet的信息,它还可以从私有网络(例如企业内部的Intranet)或者本地计算机(通过各种协议,包括文件系统)获取信息。

常见的浏览器有谷歌Chrome、火狐Firefox、苹果Safari、微软Edge等。

二、浏览器的发展历史

浏览器的发展可以跟踪到1990年,当时World Wide Web(万维网)的创造者提姆·伯纳斯-李首创了第一个浏览器,名为“WorldWideWeb”。

  1. 1993年,美国伊利诺伊大学的 Mosaic 浏览器,于年初在 Unix 平台上首次发布,随后在年末发布了为微软的Windows制作的版本。Mosaic是第一个方便使用的图形化浏览器。

  2. 1994年,前 Mosaic 成员创建了Netscape公司。Netscape 的浏览器 Navigator 几乎立即就占领了 90% 以上的市场份额。

  3. 1995年,微软推出的 Internet Explorer 开始与 Netscape Navigator 竞争,因为其随Windows系统赠送的原因,逐步占领了市场。

  4. 1998年,Netscape开放了其浏览器的源代码,这推动了Mozilla计划的出现,最终 Foster 在 2002 年发布了 Mozilla FireFox。这款开源浏览器逐渐发展成为微软 IE 的威胁,它为改善 web 标准和性能做出了巨大努力。

  5. 2003年,Apple 推出自家的浏览器 Safari。基于现代的渲染引擎KHTML(后来改名为Webkit),提供更快的速度和更好的标准支持。

  6. 2008年, Google 发布Chrome浏览器。他们发布了一个更快,更安全,更稳定且在许多方面都领先于竞争对手的浏览器。

  7. 2015年,微软随 Windows 10 发布了新的浏览器 Edge,用以取代 IE

以上就是浏览器发展的大致历史。不过,值得注意的是,尽管浏览器的外观和功能已经发生了巨大的变化,但浏览器的基本工作方式——即获取网页,渲染网页,并将其展示给用户——仍然保持不变

三、浏览器内核

浏览器内核,有时也被称为布局引擎或渲染引擎,是浏览器软件的核心部分。它负责解析网络服务提供的内容,如HTML文档、CSS样式、JavaScript程序等,然后将这些内容呈现到我们的设备屏幕上。

浏览器内核的主要作用集中在以下几个点:

  1. 内容呈现:浏览器通过其内核解析和呈现页面内容,包括图像、视频、文字等。

  2. 样式处理:浏览器内核负责解析和应用CSS样式,以确定页面内容的显示样式。

  3. 交互处理:内核处理JavaScript等脚本语言,以实现用户与页面的交亡,如响应用户点击,加载动态内容等。

  4. 安全机制:现代浏览器内核还提供了一系列安全机制,如同源策略、内容安全策略等,以保障用户在浏览网页时的安全。

不同的浏览器可能使用不同的内核,比如ChromeSafari分别使用BlinkWebKitFirefox使用GeckoIE使用TridentEdge早期版本使用EdgeHTML,现在转为使用Blink。不同的内核有自己独特的实现方式和特性,也可能导致在不同浏览器下网页表现的不同。因此在网页开发中,开发者会尽量让网页在各个主流浏览器内核下都能正常工作,这就需要考虑和处理浏览器兼容性问题。

四、渲染引擎

浏览器的渲染引擎主要负责把网页的 HTML、CSS 和 JavaScript 等资源转换(或者说渲染)为用户可以看到并与之交互的网页

1. 组成部分

浏览器的渲染引擎主要由以下几部分组成

  1. HTML解析器:将HTML代码转换为AST(抽象语法树)。
  2. CSS解析器:将CSS代码转换为CSSOM树(CSS对象模型)。
  3. DOM树:将HTML解析的结果以树形结构进行表示,便于之后与CSSOM树进行合并。
  4. JavaScript引擎:执行JavaScript代码,可能会修改DOM树和CSSOM树。
  5. 渲染树(Render Tree):是DOM和CSSOM树合并后生成的树,用于进行页面的渲染。
  6. 布局(Layout):计算出元素在最终屏幕上显示的位置。
  7. 绘制(Paint):按照计算出的规则,画出像素点。
  8. 合成(Compositing):将多个层合并成一个平面,并最终绘制到屏幕上。

注:具体每个浏览器的渲染引擎组成和工作过程可能会有所不同,以上是一般化的简化流程。

2. 工作流程

以下是渲染引擎的工作流程

  1. 解析HTML,生成DOM Tree:

    输入:HTML文档

    浏览器引擎:HTML解析器

    输出:DOM Tree

    (在这个过程中,HTML解析器遇到link标签(CSS文件)或者style标签(CSS样式)会接下来进行下一步)

  2. 解析CSS,生成CSSOM Tree:

    输入:CSS样式

    浏览器引擎:CSS解析器

    输出:CSSOM Tree

  3. 结合DOM Tree和CSSOM Tree生成Render Tree:

    输入:DOM Tree、CSSOM Tree

    浏览器引擎:样式计算

    输出:Render Tree

  4. 对Render Tree进行布局,计算每个节点的位置大小:

    输入:Render Tree

    浏览器引擎:布局(Layout)

    输出:Layout Tree

  5. 通过显卡绘制像素到屏幕上:

    输入:Layout Tree

    浏览器引擎:绘制(Painting)

    输出:Pixel on Your Screen

  6. JavaScript:在这个过程中,如果 HTML 包含 JavaScript,并且是在文档解析时就执行(不是文档解析完后加载执行),那么解析器会暂停 DOM 的构建,并执行这段 JavaScript。
    这个过程会在你初次打开网页时发生,同时当你对网页进行如滚动、点击、输入等操作,或者Javascript动态改变了DOM 或 CSSOM时也会触发这个过程。

渲染引擎在解析 HTML 文档的过程中,一旦遇到指向外部 CSS 文件或者 JavaScript 文件的链接,就开始下载它们,还会把控制权交给 JavaScript 引擎,如果有必要的话。

这个过程可能会多次重复,因为 JavaScript 可能会修改 DOM 和 CSSOM,这可能会触发重布局和重绘。

以上就是浏览器渲染引擎的工作流程。

五、线程和进程

1. 线程和进程的关系

进程和线程都是系统进行资源分配和调度的基本单位,但二者存在本质区别。

进程是系统进行资源分配和调度的一个独立单位;线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程可以创建和撤销多个线程,同一个进程中的多个线程之间可以并发执行。线程也有它自己的寄存器上下文和系统资源,并且线程之间可以共享进程的系统资源,如文件,内存等。

进程和线程的关系:

  1. 一个线程至少属于一个进程:线程是进程的一个实体,一个进程(程序)可以有多个线程并行执行。
  2. 资源分配给进程,同一进程内的线程共享该进程的资源:一个进程拥有的资源,比如文件数据、内存空间等,都可以被其内部的所有线程共享和使用。
  3. 线程可以并发执行,进程则必须在不同的时间点上运行(注:这里的进程指的是单核情况下,多核或多CPU的情况,可以多个进程同时进行)。
  4. 改变主线程,进程随之销毁,但改变子线程并不影响进程本身,也就是说,子线程会随着主线程的消亡而消亡,反之则不会。

总结来说,来自同一进程的线程共享相同的运行环境,而不同的进程则有不同的运行环境。线程让进程内并发处理成为可能,进程让操作系统的并发处理成为可能。

2. 浏览器中的线程和进程

浏览器是多进程的,每个Tab页就是一个独立的进程。这种设计的好处是,当某个Tab页出现问题崩溃时,不会影响到其他的Tab页,提高了浏览器的稳定性。

对于每个Tab页进程来说,又分为多个线程,包括:渲染线程、JS引擎线程、HTTP请求线程等等。这几个线程之间会相互配合,共同完成页面的加载、渲染、交互等任务。

所以,浏览器中的进程和线程的关系就是:每个进程包含多个线程,不同的线程执行不同的任务。

3. JavaScript中的进程和线程

JavaScript本身是单线程的,也就是说其执行环境中同一时间只能进行一项工作,如果有多项任务,就需要排队,前一个任务完成后再执行下一个任务。这种模式对于没有用户界面,不需要与用户交互,能够快速执行并结束的后台程序来说,完全符合要求。对于用户界面程序来说,这种模式就显得不够合适,因为程序的执行需要用户的互动,不能预知会在哪个地方发生阻塞。JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。

然而,虽然JavaScript本身是单线程的,但是基于其运行的环境,例如浏览器或Node.js, 是可以支持并行执行的机制,这就涉及到了进程。在浏览器中,可以开启Web Worker来在后台线程进行运行。在Node.js中,可以通过child_process模块来开启子进程进行并行计算。

另外要提的是,JavaScript使用事件驱动模型来处理并发。这使得即使是单线程,也可以通过事件回调和Promise,async/await等异步操作,处理诸如IO等耗时的操作,达到提高程序运行效率的目的

六、在浏览器地址栏输入网址到网页呈现

  1. 用户在浏览器地址栏输入URL(➡️)
  2. 浏览器通过DNS(Domain Name System)将域名解析成IP地址()
  3. 浏览器端向服务器端发送HTTP请求()
  4. 服务器接收请求,处理完成后,发送HTTP响应回浏览器端()
  5. 浏览器接收到响应后,开始解析HTML,构建DOM(Document Object Model)树()
  6. 解析HTML过程中如果遇到CSS和JavaScript,浏览器会进行符合条件的处理:
    • CSS: 加载并解析,生成CSSOM(CSS Object Model)树()
    • JavaScript:通常会停止HTML解析,执行JavaScript代码,执行完成后再继续HTML解析(⏸️➡️〽️➡️)
  7. DOM树和CSSOM树结合,生成render树()
  8. 浏览器根据render树进行布局,计算每个节点的位置大小()
  9. 最后将render树绘制在屏幕上,展示给用户()

整个流程就像打开一扇门,浏览器是钥匙,网址是密码,解析出正确的IP地址就打开了门,然后服务器接收到请求就像客人进来,准备好服务后就把结果给客人。然后浏览器就像是将结果解析并且整理的厨师,把食物烹饪后端给客户看,客户只需享受最后的美食就好了。

总结

总的来说,了解和理解浏览器的内核与渲染原理是非常必要的。对于开发者来说,这可以帮助他们更好地理解和优化网页性能,提供更好的用户体验。对于普通用户来说,理解浏览器的内核和渲染原理可以帮助他们更好地维护和使用浏览器。浏览器的内核,决定了浏览器如何显示网页的内容和功能;而渲染原理,又决定了网页内容的解析、布局、绘制速度。未来随着网络和设备的发展,浏览器的内核和渲染技术会得到不断的更新和优化,我们有理由相信未来的浏览器将提供给我们极致的用户体验。

你可能感兴趣的:(前端性能优化,前端)