浏览器的发展历史
用户代理是啥
1 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36 |
火狐: 老猿啊,我的
Gecko
升级了,我现在支持很多新功能了,你可以更新下你的 💩 山了, 我的user-agent
是Mozilla/1.0(Windows NT 6.1; rv:2.0.1)....
老猿:wait wait soon soon
... ... IE: 老猿啊,你偏心啊,为啥老狐长这么俊,我这像挖了半辈子煤的。 老猿:别人有那 xx 功能可以让我操练操练,你有吗。 IE: 有的、有的,但你咋不用啊 老猿: 我又不知道你有没有,我只认user-agent
IE: soga IE 狐: (IE 带着老狐的user-agent
向老猿问候了一下)老猿啊,近来可好好~ 老猿:老狐啊,还好还好,你还是那么俊啊。等等,你最近是去挖煤了吗?好家伙,IE baby,原来是你,差点被你骗了。 Safari: 老猿啊老猿,我有 xx 功能,我的user-agent
有Safari AppleWebkit...
等 Chrome: 老猿啊老猿,我有 xx 功能,我的user-agent
有Chrome....
等 ...老猿:
wait wait soon soon
...ChromeSafari 狐:老猿老猿.. Chrome 狐 Safari:老猿老猿.. IESafariChrome 狐:老猿老猿.. SafariChrome 狐:老猿老猿.. .. ChromeSafari 狐:IEIE,走好 Chrome 狐 Safari:IEIE,走好 SafariChrome 狐:IEIE,走好 SafariChrome 狐:IEIE,走好 老猿: IEIE,走好
刚开始用户代理是为了表明浏览器的身份(浏览器厂商、版本号、使用的内核及其对应的版本号),老猿会为最新浏览器的功能设计不同的网页发送不同的内容,后面其他浏览器也支持相应的功能后,就会在自己的user-agent
加上对应功能浏览器的标识,来欺骗老猿,把对应的内容也发送给自己。
于是就出现了各种 ChromeSafari 狐、SafariChrome 狐等等...
内核(渲染引擎)
内核是啥?
内核就是把前端资源渲染成图像的一套系统
内核与浏览器的关系可以看作 linux 与 Centos、Ubuntu、Android 的关系,
常见的内核以及对应的浏览器
内核 | KHTML(WebKit 前身) | Trident | EdgeHTML | Gecko | WebKit |
---|---|---|---|---|---|
源码地址 | https://invent.kde.org/frameworks/khtml | https://github.com/mozilla/gecko-devhttps://hg.mozilla.org/mozilla-central/file/tip | https://github.com/WebKit/WebKit | ||
浏览器平台 | IE | Edge(老版) | 火狐 | Edge/Chromium/Chrome/Safari/Android 浏览器/ChromeOS/WebOS |
这次的主角是 WebKit,以后有空再扯其他的
内核各模块
HTML 解释器:将 HTML 文本解释成 DOM (文档对象模型)树
CSS 解释器:为 DOM 中的各个元素对象计算出样式信息
布局:在 DOM 创建之后,引擎需要将其中的元素对象同样式信息结合起来,计算它们的大小位置等布局信息,形成一个能够表示这所有信息的内部表示模型。
JavaScript 引擎:解释 JavaScript 代码并通过 DOM 接口和 CSSOM 接口来修改网页内容和样式信息,从而改变渲染的结果。
绘图:使用图形库将布局计算后的各个网页的节点绘制成图像结果。
各模块之间的工作关系
这里 JavaScript 引擎和 DOM 是分开的,所以直接操作 DOM 是有一定的成本的。
WebKit
广义 WebKit
可以理解为上面历史里面介绍的由 Apple 开源的 Webkit 项目
github 地址:GitHub - WebKit/WebKit: Official git mirror of the WebKit repository, https://svn.webkit.org/reposit
https://webkit.org/getting-the-code/#checking-out-with-subversion
源地址:https://svn.webkit.org/repository/webkit/ (牛逼的东西往往看上去如此朴素)
官网:https://webkit.org/
狭义 WebKit
先看一下 WebKit 项目的模块
狭义 Webkit 指的是 Webkit 项目中在WebCore(HTML 解释器、CSS 解释器得和布局等模块)和 JavaScript 引擎
之上的一层绑定和嵌入式编程接口,提供览器调用。
WebKit2
和狭义 WebKit 一样的绑定和嵌入式编程接口,但不是 WebKit 的简单升级,而是为了将渲染放到单独的进程中来完成,提供多进程模型的接口层。
在 Chromium 项目中,引入了跨进程的架构。
Chromium 的多进程架构是先出来的,但一直没有引入到 WebKit 项目中,所以 WebKit 项目就又创建一一套 WebKit2 接口层,Chromium 中的多进程是在 WebKit 之上。
而 WebKit2 则是将多进程结构隐藏在内部
网页结构
框结构
一个框包含一个 HTML 文档
比如使用frameset
frame
iframe
就可以为网页增加一个框
1 | <div class="main"> |
层结构
WebKit 为了方便渲染会为一些特殊的元素创建独立的层(比如 video、canvas、带 css3D 属性等),具体以后讲到 RenderLayer 树的时候再细讲,目前可以比作浏览器开发者工具里面的 Layers 面板对应的一个一个框
1 | <div> |
WebKit 如何渲染一个网页
从一个 URL 到生成最终图像的过程(常见面试题),可以把下面的内容再加上 DNS 解析、缓存可以满分,要时面试官想听更细点,可以再加上一些网络知识,比如建立连接的过程[手动滑稽]
这主要有三个过程
从网页的 URL 到构建完 DOM 树
从 DOM 树到构建完 WebKit 的绘图上下文
从绘图上下文生成最终图像
URL ==> DOM 树
当用户输入网页 URL 的时候,WebKit 调用其资源加载器加载该 URL 对应的网页。
加载器依赖网络模块建立连接,发送请求并接收答复。
WebKit 接收到各种网页或者资源的数据,其中某些资源可能是同步或异步获取的。
网页被交给 HTML 解释器转变成一系列的词语(Token)。
解释器根据词语构建节点(Node), 形成 DOM 树。
如果节点 是 JavaScript 代码的话,调用 JavaScript 引擎解释并执行。
JavaScript 代码可能会修改 DOM 树的结构。
如果节点需要依赖其他资源,例如图片、CSS、视频等,调用资源加载器来加载它们,但是它们是异步的,不会阻碍当前 DOM 树的继续创建;如果是 JavaScript 资源 URL (非异步方式),则需要停止当前 DOM 树的创建,直到 JavaScript 的资源加载并被 JavaScript 弓|擎执行后才继续 DOM 树的创建。
DOM 树构建完成:document.DOMContentLoaded
DOM 树构建完成且依赖的资源(各种 js,css,图片,字体等)加载完:window.onload
CSS 和 DOM 树 ==> RenderObject 树到渲染上下文
CSS 文件被 CSS 解释器解释成内部表示结构
CSS 解释器工作完成之后,在 DOM 树上附加解释后的样式信息,形成 RenderObject 树
RenderObject 节点在创建的同时,WebKit 根据网页的层次结构创建 RenderLayer 树,同时构建一个虚拟的绘图上下文。
绘图上下文 ==> 最终图像
绘图上下文是一个与平台无关的抽象类,它将每个绘图操作桥接到不同的具体实现类,也就是绘图具体实现类。
绘图实现类也可能有简单的实现,也可能有复杂的实现。
绘图实现类将 2D 图形库或者 3D 图形库绘制的结果保存下来,交给浏览器来同浏览器界面一起显示。
整个流程
渲染的整个大体流程就是这个样子了,每一小环节的具体内容,以后再说
未完待续...
Gitalk 加载中 ...