浏览器工作原理 - 从url到页面展示浏览器都做了哪些不为人知的事(内附流程图)

浏览器

相信做web开发的对浏览器并不陌生。简单来说浏览器就是一个由地址栏、菜单栏、选项卡、页面窗口、和状态栏组成的应用程序,但这仅仅是我们从表面上看到的。那么实际来讲远远不止这些,在浏览器的背后还有更多更复杂的逻辑和组件,比如浏览器引擎,渲染引擎,js解释器,网络,数据存储等等。

浏览器内核

浏览器内核分为:渲染引擎和js引擎两部分,由于js引擎越来越独立,内核也就倾向于只指渲染引擎了,主要负责将网络请求回来的资源加以解析排版然后呈现给用户。

不同浏览器有着不同的内核。在五大主流浏览器中就包含了四中内核:

IE浏览器使用的是Trident内核

Firefox使用的是gecko内核

safari浏览器使用的是webkit内核

chrome浏览器早期使用的也是webkit内核,13年开始使用Blink内核

Opera浏览器最早使用的是Presto内核,后来弃用改为webkit内核,然后又紧随chrome使用了Blink内核。

浏览器工作原理

那么当我们在地址栏里输入一个url到一个漂亮的页面呈现在我们面前时,这期间到底发生了些什么呢?接下来我们来看一个图:

上图简单的展示了从我们输入一个url到浏览器呈现给我们一个漂亮的页面的整个过程,下面我们来一步一步进行解析:

第一步当我们在地址栏中输入url并按下回车,这时浏览器会构建一个http request,然后通过网络进程去请求DNS(域名解析服务器),通过DNS会将url中的域名转换成目标服务器对应的IP地址和端口号。然后再通过IP地址和端口号与目标服务器建立TCP连接,连接建立成功目标服务器收到请求后,会根据请求信息构建一个http response即响应,然后将要访问内容通过http response返回给浏览器,到此就完成了一次请求,浏览器就得到了我们想要的内容。接下来就是浏览器会把得到的响应内容进行解析然后变成一个漂亮的页面。

 在上一步中浏览器得到的实际是一段HTML代码,如下图所示:

在得到html代码后,浏览器会在内存条中开辟一块栈内存 ,用来给代码的执行提供环境,同时分配一个主线程用来逐行进行解析和执行代码。我们都知道JavaScript语言最大的特点就是单线程的,也就是说同一时间只能做一件事,所以这里就涉及到了一个专业术语:“进栈执行,执行完出栈”。也就是说在进行逐行html代码解析时,一定要等到上一行代码执行结束并且出栈后,主线程才会空出,下一行代码才能进栈执行。

但有个特殊情况,就是在解析的过程中如果遇到link/script/img/audio/vedio等请求后,浏览器会开辟一个全新的线程去请求这些资源,原来的主线程会继续执行下面的代码。需要注意的是这里的新线程跟上面所说的主线程进栈出栈并不冲突。我们说JavaScript是单线程执行的,但浏览器是可以多线程的。也就是说js在执行代码时是单线程一步一步执行的,当遇到一些特殊标签(如link/script/img)时,浏览器就会再开辟一个新线程去单独的执行这些代码,而主线程继续执行下面的代码,这样就不会因为网络或其它原因造成堵塞了。

举个例子:假如一个饭店只有一个服务员既负责点菜又负责上菜,某天她正在给A桌的客人点菜,正在这时厨师通知她说B桌的菜做好了,可以上菜了,但是由于一个人同一时间只能做一件事(相当于js是单线程执行),所以只能等到A桌点完菜才能去给B桌上菜,这时B桌的客人就急了,我的菜都做好了怎么还不给上啊,下次不来了。老板一听也急了觉得这样可不行啊,效率太低了,于是当即决定再招一个服务员(相当于浏览器又开辟了一个新线程),这样一来a服务员在给A桌点菜的同时,b服务员可以给B桌继续上菜。

当返回来的代码自上而下全部执行完毕后会生成一个DOM树。

在上一步中我们已经得到了一颗DOM树,但只是一个光秃秃的,没有任何装饰的DOM树,接下来我们就来为这颗树加一些装饰--CSS解析

我们都知道,当我们访问一个网站时之所以能看到各种各样漂亮页面,是因为有着CSS的强大支撑。页面中所有的css有样式表CSSStyleSheet集合构成,而CSSStyleSheet是一系列CSSRule的集合,每一条cssrule则由选择器selector部分和声明declaration构成,而declaration是css属性和值即Key-Value的集合。

CSS解析完成后会进行cssrule的匹配过程,即寻找满足每条css规则selector部分的HTML元素,例如类选择器.text-color,会去匹配所有HTML元素中class=“text-color”的标签,然后将其Declaration部分应用于该元素上,其它选择器也是同理。实际的规则匹配过程会考虑到默认和继承的css属性以及规则的优先级等因素。

至此,就完成了对cssrule的解析。

 在上一步中我们完成了对css的解析,那么接下来就是将css rule应用到HTML元素上。首先我们需要计算布局,布局就是安排和计算页面中每个元素大小位置等几何信息的过程。HTML采用流式布局模型,基本的原则是页面元素在顺序遍历过程中一次按从左到右,从上至下的排列方式来确定各自的位置区域。

一个HTML元素对应一个以CSS盒子模型描述的方块区域,HTML元素分成两个基本类型,Inline和Block。Inline元素不会换行,按从左到右来布局。Block元素的出现意味着需要从上到下换到下一行来布局。除了这种基本的顺序安装元素的Inline和Block来进行流式布局外,还有特殊指定的一些布局方式,如absolute/relative/fixed/flex以及float浮动布局。

经过了layout阶段的处理,我们已经把带有css的DOM树变成了一颗带有布局信息的DOM树,接下来就是对DOM的渲染和绘制了。

经过上面的步骤我们已经将HMTL、CSS分别解析出来并通过布局得到了一颗带有布局信息的DOM树,接下来就是通过渲染将内容呈现出来了。这里会用到Paint模块,它负责将带有布局信息的DOM树映射成可视的图形,它会遍历DOM树调用每个节点的绘制方法将其内容显示在一块画布或者位图上,并最终呈现在浏览器应用窗口成为用户看到的实际页面,其中每个节点大小和位置等信息在上一步layout阶段都已经计算好了,节点的内容取决于对应的HMTL元素,或是文本,或是图片等等。

通常情况下,布局和绘制是相当耗时的操作。如果DOM树每次略有改动都要重新布局和绘制一次,这就是所说的回流和重绘,效率会相当低下。因此一般浏览器内核都会实现一种增量布局和增量绘制的方式。当DOM树节点内容或样式发生变化时,内核会确定其影响范围,在布局阶段会标记出受该节点影响的其它节点,在绘制阶段会标记出一个dirty区域并通知系统重绘。因此在日常开发中一定要尽量减少回流和重汇的发生以提高程序的性能。

 从资源的下载到最终的页面呈现,其渲染流程可简单的理解成一个线性串联的变换过程组合,原始输入为url地址,最终输出为页面Bitmap,中间依次经历了Loader,Parser,Layout,Paint模块,最终形成了一个页面Bitmap。

以上就是浏览器的工作原理。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值