浏览器的运作方式


在这里插入图片描述

一、为什么要了解浏览器的运作方式?

    首先,浏览器的运作方式是经常在面试题中出现的,其次,对于一名前端工程师而言,只有了解浏览器的运作方式,我们在书写页面时才能尽可能的提高浏览器的效率。举一个例子,一般电脑的刷新频率是60Hz,也就是刷新一次是1/60=16ms。换句话说,如果页面的加载和渲染时间超过了16ms,那么将会出现卡顿现象。

二、浏览器的发展历史

    1991年Berners Lee建立了第一代网络浏览器World Wide Web,这个与万维网虽然在名称上是一样的,但是本质是一个只支持显示文本和图片的浏览器,除了基本的访问网页资源外,还兼具了一些HTML编译器的功能。(Berners Lee也参与了万维网的创作,有web之父的称号),后来,为了避免与网络信息空间重名,改名为 Nexus。
    1993年Mosaic浏览器问世,一经推出就受到了广大用户欢迎,在内容上仍然是支持文本和图片,它将web带向了大众,对于Internet的发展具有重要作用。
    1994年由网景公司推出的Netscape浏览器,是世界上第一款商用浏览器,其程序员是原来参与开发Mosaic浏览器。在内容上只能显示简单的html,没有css和js,占领了较大的浏览器的市场份额。
    与Netscape浏览器同年,Opera浏览器诞生,支持多页面标签式浏览,是跨平台浏览器可以在Windows、Mac和Linux三个操作系统平台上运行。
    1995年微软发布IE1.0和IE2.0浏览器,出现了不同的浏览器之间的市场竞争,之后1996年Windows集成IE3.0,虽然网景公司此时的市场份额为86%,但是微软凭借其与Windows系统的绑定效应,最终在取代了网景公司,1999年市场份额达到了99%。
    需要补充说明的是,在1998年,网景公司在商场不利的情况下成立了Mozilla基金会,在该基金会的推动下,创作出了Firefox浏览器并将项目开源,并与2004年发布了第一版,拉开了第二场浏览器竞争。
    2003年苹果发布了Safari浏览器,和Windows一样,Safari浏览器被包含在苹果系统产品中,2005年苹果公司开源其内核webkit。
    2008年谷歌利用苹果开源的webkit内核,创建了Chrome浏览器并将其内核blink开源,目前Chrome浏览器已成为全球最受欢迎的浏览器。
    随后,IE的用户体验逐步下降,虽然2015年IE基于Chrome浏览器内核blink创作了Edge,但是已经凉了。
    目前市场份额为:Chrome 64%,可以说Chrome浏览器已经终结了这场前前后后的竞争。
    浏览器的内核总结:IE浏览器(Trident),Firefox浏览器(Gecko),Safari浏览器(Webkit),Chrome/Opera/Edge浏览器(Blink),不得不说Safari的webkit开源对于浏览器的发展具有重大贡献。

在这里插入图片描述

三、浏览器的整体结构

    虽然前前后后参与这样竞争的浏览器有很多,但是在结构上有较大的相似性。具体内容如下:
在这里插入图片描述
这里补充一下:像知道MIME媒体类型点击这里

在这里插入图片描述

四、浏览器的进程与线程

    首先,如果想要弄明白浏览器的运行过程,首先需要明白进程和线程两个关键概念:
    进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程一般由程序,数据集合和进程控制块三部分组成。程序用于描述
进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块包含进程的描述信息和控制信息是进程存在的唯一标志。
    线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。
    进程与线程的区别与联系:
1. 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
3. 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;
4. 调度和切换:线程上下文切换比进程上下文切换要快得多。
    程序运行中的进程与线程:
在这里插入图片描述
    目前通用的浏览器是多进程结构,但是早期的浏览器是单进程的。在早期的浏览器中,浏览器的单进程包含页面线程和js线程的,由于线程之间是共享资源的,这就导致一个线程出问题,整个浏览器运行效果受到影响。表现为一个页面无法加载,其他加载的页面也会受到影响。其次单进程浏览器的线程资源共享导致不安全,最后就是性能方面,由于线程可能需要负责多个页面的解析和渲染,导致性能上不太稳定或者加载较慢。以Chrome浏览器为例,目前的多进程浏览器的进程如下图所示:
在这里插入图片描述
对于Chrome浏览器,存在一下四种不同的进程模型:
(1)Process-per-site-instance:不同站点页面以及同一站点的不同页面是彼此隔离的,分别会创建不同的进程,Chrome浏览器默认会使用这种模型,这种模型也更加安全;
(2)Process-per-site:同一站点使用同一个进程;
(3)Process-per-tab:一个tab栏中使用同一个进程(无论同一个tab栏中的不同站点是否有联系);
(4)Single Process:最开始的单进程浏览器。

在这里插入图片描述

五、浏览器的运行过程(重难点)

    当用户输入的是“东京奥运会”并按下回车时,浏览器会将内容锁定为关键词,于是会使用默认配置的搜索引擎来查询。
    当用户输入https://www.baidu.com并按下回车时,浏览器线程会启动网络线程进程DNS域名解析,之后连接服务器获取数据。
    好,接下来是重难点内容。


    首先网络进程通过SafeBrowsing(Chrome浏览器中的站点安全系统,采用的原理包含黑名单IP匹配等)来检测你输入的网址是否为恶意站点,如果是则弹出警告,当然用户也可以强行访问该目的站点。

    当返回数据准备完毕且通过安全检测时,浏览器进程会创建一个渲染器进程来渲染页面,浏览器进程通过IPC管道将数据传递给渲染层,接下来渲染层页面需要将html、css、js等资源渲染成一个可以交互的用户界面,渲染器的工作过程如下:
在这里插入图片描述
    接下来,对于右侧得到的dom树,渲染器进程会通过样式计算以及浏览器的默认样式对dom树进行渲染并生成一个Layout tree,Layout tree对于每个节点都会记录起始的(x,y)、宽高以及边框尺寸。需要补充说明的是:dom数与Layout tree并不是一一对应的,dom树中节点为display:none的节点不会出现在Layout tree上,对于before和after伪类,content内容不会出现在dom树中但是会出现在Layout tree里面。
    前面的步骤可以总结为知道我们要绘制什么内容,接下来渲染器进程需要知道绘制顺序,故而会利用主线程遍历Layout tree并创建一个绘制记录表。例如,对于z-index会影响节点绘制的层级关系,也就是说不能够仅仅按照dom树中节点的层级关系自上而下的绘制。在生成绘制顺序记录表之后,主线程再次遍历Layout tree生成Layor tree并将Layor tree 和绘制顺序记录表传递给合成器线程。
    接下来就是真正的绘制了,此过程被称为栅格化。对于Chrome,早期的栅格化只是栅格化用户可见内容,也就是说,当用户滚动右侧导航条时需要进行重新栅格化还未出现过的内容,很显然容易出现加载延时,影响用户体验。目前优化后的Chrome使用的栅格化方法为合成栅格化,将页面的多个部分分成多个图层分别进行栅格化(由栅格线程来完成,栅格化页面的所有内容而不仅仅是可视区),栅格化完成后会将栅格化图层存入GPU内存中。之后,合成器线程会根据当前可视区收集被称为Draw Quads的图像信息,Draw Quads则记录了图块在GPU内存中的位置和浏览器页面中需要放置的位置。合成器线程利用这些信息生成了一个合成器帧,并通过IPC传递给浏览器进程,接下来浏览器进程将合成器帧传递给GPU,最后GPU将此帧渲染展示到浏览器页面上。
    还有一件事,用户可能通过右部滑动导航栏,这时由于之前的图层都是栅格化好了的,浏览器只需要再次根据改变后的可视化区域重新收集Draw Quads图像信息块合成新的合成器帧,再进行上述相同流程。

六、浏览器的卡顿原因及优化方式

    在了解页面卡顿原因之前,先要了解一下重排重绘两个概念:
重排:当我们修改了dom元素的尺寸和位置属性时,渲染器主线程会重新进行样式计算、布局、绘制以及之后的流程,这种行为就是重排;
重绘:当我们修改某个dom元素的颜色属性时,并不会重新触发布局,但是会触发样式计算和绘制以及之后的流程,这个便是重绘。
    重排和重绘都会占用主线程,而我们知道js也会占用主线程,这样便出现了抢占主线程使用权的问题。存在一个这样的场景:有一个动画(显然会不断导致重排),拿电脑的60Hz的刷新频率来说,如果动画在16ms内执行完成,将会拿到主线程的使用权,如果js的循环太多导致js无法及时归还主线程的使用权,在下一次执行时来不及进行重绘,当js用完后再归还,重绘拿到使用权进行重新渲染,这便出现了卡顿。
    优化方法如下:
(1)利用requestAnimationFrame()API来解决,原理:站在js的角度,控制js的占用时间,类似于settimeout函数,但是requestAnimationFrame函数能够同步浏览器的刷新频率,将每一次动画后需要执行的js分成几个小的部分来执行,并分发给每一帧来处理。

(2)对动画的处理,尽可能采用transform来替换,原理:站在动画的角度优化,减少动画时间为js预留更多的时间,transform属性不会经过布局和绘制,直接运行在合成器线程和栅格化线程中,能够节省运算时间,transform包含位置变换、伸缩变换以及旋转变换。

在这里插入图片描述

核心参考:
哔哩哔哩视频——浏览器是如何运作的

辅助参考:
各大浏览器的发展历史
浏览器的主要结构
进程与线程
requestAnimationFrame详解以及无线页面优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌空暗羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值