前言
可以说浏览器是前端开发者必备的工具,也是前端开发者将成果展现给用户的方式之一,没有对浏览器有着深刻的认识,怎么能说自己是前端开发者呢?了解了浏览器的运行轨迹个特征,无疑对代码的优化和渲染的优化和用户体验有着质的飞跃。
所以
一位程序员的职业生涯大约十年,只有人寿命的十分之一。前端项目只是你生活工作的一部分,而你却是它的全部,你是他的灵魂。请放下长时间的游戏、工作时的摸鱼。多学习来以最完美的状态好好陪你项目!
正文
上面是凑字数的,接下来非常重要,请不要走开!
知识点
- 主流浏览器内核(简)
- 浏览器的基本架构(重)
- 如何保证⻚面文件能被完整送达浏览器?
- 为什么很多站点第二次打开速度会很快?
主流浏览器内核(简)
浏览器/RunTime | 内核(渲染引擎) | JavaScript 引擎 |
---|---|---|
Chrome | webkit | V8 |
FireFox | Gecko | SpiderMonkey |
Safari | Webkit | JavaScriptCore |
Edge | EdgeHTML | Chakra(for JavaScript) |
IE | Trident | JScript(IE3.0-IE8.0) |
Opera | Presto->blink | Linear A(4.0-6.1)/ Linear B(7.0-9.2)/ Futhark(9.5-10.2)/ Carakan(10.5-) |
Node.js | V8 |
浏览器的基本架构(重)
- 仅仅打开了1个⻚面,为什么有4个进程?
- 线程与并行处理
- 进程 Vs 线程
- 从古至今浏览器演变
仅仅打开了1个⻚面,为什么有4个进程?
Chrome在打开一个页面时,任务管理器缺打开了多个进程?为什?这就要了解一下相关进程与线程的基本概念与Chrom架构,接下来我们先看进程与线程。
进程、线程与并行处理
并行处理bi: 同一时刻处理多个任务,称为并行处理。
线程: 分为多线程和单线程,如其名(当一个任务分为多个小任务的同时缺只有一位童鞋在进行称为单线程,而多为童鞋同时进行多个小任务,成为多线程)看这段解释,第一概念显然是,多线程耗时短,需要更多的人力量,单线程则相反。 结合并行处理就知道,
多线程可ui并行处理,但是线程不能单独存在,线程是由进程管理的
进程 Vs 线程
一个进程就是一个程序的运行实例。 详细解释就是,启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。
从图中得出以下几点总结
- 线程是依附于进程的,而进程中使用多线程并行处理能提升运算效率。
- 进程中的任意一线程执行出错,都会导致整个进程的崩溃。
- 线程之间共享进程中的数据。
- 当一个进程关闭之后,操作系统会回收进程所占用的内存
- 进程之间的内容相互隔离
我们仔细看这张图将一段任务分为4个小任务,而4个小任务存在三个线程一个进程中,线程之间共享进程中的数据。
从古至今浏览器演变
- 单进程浏览器时代
- 多进程浏览器时代
- 未来面向服务的架构
单进程浏览器是指浏览器所以模块都运行再同一个进程里 ,这些模块包含了网络、插件、JavaScript 运行环境、渲染引擎和页面等。
显然缺点很明显
- 不稳定
- 不流畅
- 不安全 可以想象,当一个插件或者脚本出现问题,导致当前进程非常慢,严重的话直接浏览器奔溃..
早期多进程架构
- 一个页面一个进程,多个线程
- 进程是相互隔,当一个页面或者插件崩溃时,影响到的仅仅是当前的页面进程或者插件进程,并不会影响到浏览器和其他页面(稳定)
- JavaScript 也是运行在渲染进程中的,所以即使 JavaScript 阻塞了渲染进程,也只会影响当前进程和也页面。当关闭一个页面时,整个渲染进程也会被关闭,之后该进程所占用的内存都会被系统回收(流畅)
- 多进程架构的额外好处是可以使用安全沙箱 ,你可以把沙箱看成是操作系统给进程上了一把锁,沙箱里面的程序可以运行,但是不能在你的硬盘上写入任何数据,也不能在敏感位置读取任何数据,例如你的文档和桌面。Chrome 把插件进程和渲染进程锁在沙箱里面,这样即使在渲染进程或者插件进程里面执行了恶意程序,恶意程序也无法突破沙箱去获取系统权限。(安全)
目前多进程架构
从图中可以看出,最新的 Chrome 浏览器包括:1 个浏览器(Browser)主进程、1 个 GPU 进程、1 个网络(NetWork)进程、1 个存储(Storage)进程、多个渲染进程和多个插件进程。
总结一下👇
-
浏览器进程。主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
-
渲染进程。核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
-
GPU 进程。其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程。
-
网络进程。主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。
-
存储进程。主要负责页面的本地存储,最新Chrome发现已经独立
-
插件进程。主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。
未来面向服务的架构 为了解决这些问题,在 2016 年,Chrome 官方团队使用"面向服务的架构"(Services Oriented Architecture,简称 SOA)的思想设计了新的 Chrome 架构
Chrome 最终要把 UI、数据库、文件、设备、网络等模块重构为基础服务,类似操作系统底层服务。
了解了浏览器的架构设计,进入下一环节
如何保证⻚面文件能被完整送达浏览器?
- TCP / IP 传输数据包
- HTTP,还是使用WebSocket,它们都是基于TCP/IP的
在衡量Web⻚面性能的时候有一个重要的指标叫"FP(First Paint)FP(FirstPaint) ",是指从⻚面加载到首次开始绘制指从⻚面加载到首次开始绘制的时⻓的时⻓。这个指标直接影响了用戶的跳出率,更快的⻚面响应意味着更多的PV、更高的参与度,以及更高的转化率。那什么影响FP指标呢?其中一个重要的因素是网络加载速度网络加载速度
在网络中,一个文件通常会被拆分为很多数据包来进行传输,而数据包在传输过程中又有很大概率丢失或者出错。那么如何保证⻚面文件能被完整地送达浏览器呢?
1. IP:把数据包送达目的主机 数据包要在互联网上进行传输,就要符合网际协议网际协议(Internet Protocol,简称IP)标准
计算机的地址就称为IP地址,访问任何网站实际上只是你的计算机向另外一台计算机请求信息
- 上层将含有"掘金"的数据包交给网络层;
- 网络层再将IP头附加到数据包上,组成新的 IP数据包IP数据包,并交给底层;
- 底层通过物理网络将数据包传输给主机B;
- 数据包被传输到主机B的网络层,在这里主机B拆开数据包的IP头信息,并将拆开来的数据部分交给上层;
- 最终,含有"掘金"信息的数据包就到达了主机B的上层了。
2. UDP:把数据包送达应用程序
用戶数据用戶数据包协议包协议(User Datagram Protocol )",简称UDP ,UDP中一个最重要的信息是端口号端口号
为了支持UDP协议,我把前面的三层结构扩充为四层结构,在网络层和上层之间增加了传输层,如下图所示:
增加一个操作 在传输层,数据包中的UDP头会被拆开,并根据UDP中所提供的端口号,把数据部分交给上层的应用程并根据UDP中所提供的端口号,把数据部分交给上层的应用程序序;
以上这些会产生一些缺点:
- UDP不能保证数据可靠性,但是传输速度却非常快
- 数据包在传输过程中容易丢失;
- 大文件会被拆分成很多小的数据包来传输,这些小的数据包会经过不同的路由,并在不同的时间到达接收端,而UDP协议并不知道如何组装这些数据包,从而把这些数据包还原成完整的文件
3.TCP:把数据完整地送达应用程序
TCP(TransmissionControlProtocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议连接的、可靠的、基于字节流的传输层通信协议。相对于UDP,TCP有下面两个特点:
- 对于数据包丢失的情况,TCP提供重传机制;
- TCP引入了数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件。
一个完整的TCP连接的 生命周期包括了"建立连接建立连接 ""传输数据传输数据 "和"断开连接断开连接 " 三个阶段。
- 首先,建立连接阶段。这个阶段是通过"三次握手"来建立客戶端和服务器之间的连接。TCP 提供面向连接的通信传输。面向连接面向连接是指在数据通信开始之前先做好两端之间的准备工作。所谓三次握手三次握手,是指在建立一个TCP连接时,客戶端和服务器总共要发送三个数据包以确认连接的建立。
- 其次,传输数据阶段其次,传输数据阶段。在该阶段,接收端需要对每个数据包进行确认操作接收端需要对每个数据包进行确认操作,也就是接收端在接收到数据包之后,需要发送确认数据包给发送端。所以当发送端发送了一个数据包之后,在规定时间内没有接收到接收端反馈的确认消息,则判断为数据包丢失,并触发发送端的重发机制。同样,一个大的文件在传输过程中会被拆分成很多小的数据包,这些数据包到达接收端后,接收端会按照TCP头中的序号为其排序,从而保证组成完整的数据。
- 最后,断开连接阶段,数据传输完毕之后,就要终止连接了,涉及到最后一个阶段"四次挥手"来保证双方都能断开连接。
到这里你应该就明白了,TCP为了保证数据传输的可靠性,牺牲了数据包的传输速度,因为"三次握手"和"数据包校验机制"等把传输过程中的数据包的数量提高了一倍。 也知道了如何保证⻚面文件能被完整地送达浏览器呢
为什么很多站点第二次打开速度会很快?
HTTP请求流程
为了便于你理解,先看一张HTTP 请求示意图,用来展现浏览器中的 HTTP 请求所经历的各个阶段。
从图中可以看到,浏览器中的 HTTP 请求从发起到结束一共经历了如下八个阶段:
- 构建请求
- 查找缓存
- 准备 IP 和端口
- 等待 TCP 队列
- 建立 TCP 连接
- 发起 HTTP 请求
- 服务器处理请求
- 服务器返回请求和断开连接
为了更好的把以上八个阶段讲清楚,我们举个具体的例子来说吧💪
浏览器端发起 HTTP 请求流程
如果你在浏览器地址栏里键入百度网站的地址:www.baidu.com, 那么接下来,浏览器会完成哪些动作呢?下面我们就一步一步详细"追踪"下。
1. 构建请求
首先,浏览器构建请求行信息(如下所示),构建好后,浏览器准备发起网络请求。
bash
GET /index.html HTTP1.1
2. 查找缓存
在真正发起网络请求之前,浏览器会先在浏览器缓存中查询是否有要请求的文件。其中,浏览器缓存是一种在本地保存资源副本,以供下次请求时直接使用的技术。
当浏览器发现请求的资源已经在浏览器缓存中存有副本,它会拦截请求,返回该资源的副本,并直接结束请求,而不会再去源服务器重新下载。这样做的好处有:
-
缓解服务器端压力,提升性能(获取资源的耗时更短了);
-
对于网站来说,缓存是实现快速资源加载的重要组成部分。
当然,如果缓存查找失败,就会进入网络请求过程了。
3. 准备 IP 地址和端口
不过,先不急,在了解网络请求之前,我们需要先看看 HTTP 和 TCP 的关系。因为浏览器使用 HTTP 协议作为应用层协议 ,用来封装请求的文本信息;并使用 TCP/IP 作传输层协议 将它发到网络上,所以在 HTTP 工作开始之前,浏览器需要通过 TCP 与服务器建立连接。也就是说 HTTP 的内容是通过 TCP 的传输数据阶段来实现的,你可以结合下图更好地理解这二者的关系。
那接下来你可以思考这么"一连串"问题:
- HTTP 网络请求的第一步是做什么呢?结合上图看,是和服务器建立 TCP 连接。
- 那建立连接的信息都有了吗?建立 TCP 连接的第一步就是需要准备 IP 地址和端口号。
- 那怎么获取 IP 地址和端口号呢?这得看看我们现在有什么,我们有一个 URL 地址,那么是否可以利用 URL 地址来获取 IP 和端口信息呢?
你会发现记住域名比IP更加的方便,所以基于这个需求又出现了一个服务,负责把域名和 IP 地址做一一映射关系。这套域名映射为 IP 的系统就叫做"域名系统 ",简称 DNS(Domain Name System)。
所以,这样一路推导下来,你会发现在第一步浏览器会请求 DNS 返回域名对应的 IP 。当然浏览器还提供了 DNS 数据缓存服务,如果某个域名已经解析过了,那么浏览器会缓存解析的结果,以供下次查询时直接使用,这样也会减少一次网络请求。
拿到 IP 之后,接下来就需要获取端口号了。通常情况下,如果 URL 没有特别指明端口号,那么 HTTP 协议默认是 80 端口。
DNS解析想深入了解的话,有兴趣的可以看看这篇文章DNS 原理入门
4. 等待 TCP 队列
现在已经把端口和 IP 地址都准备好了,那么下一步是不是可以建立 TCP 连接了呢?
答案不一定的,这个得根据不同的浏览器来规定的,我们以Chrome浏览器为例,Chrome 有个机制,同一个域名同时最多只能建立 6 个 TCP 连接,如果在同一个域名下同时有 10 个请求发生,那么其中 4 个请求会进入排队等待状态,直至进行中的请求完成。
当然,如果当前请求数量少于 6,会直接进入下一步,建立 TCP 连接。
这里其实也就可以出个小面试题,那有很多图片资源或者其他支援请求怎么办?
5. 建立 TCP 连接
- 这里面要细讲的话,内容就多了,比如三次握手建立连接,四次挥手断开连接,上文已经讲了哦!
6. 发送 HTTP 请求
上面大概讲完了建立TCP连接,你可以理解TCP的连接,是为了保证浏览器跟服务器更好的通信。当然了有了上面的这个过程中, HTTP 中的数据也正是在这个通信过程中传输的。
那么我们从一张图片中来看,浏览器是如何发送信息给服务器的👇
- 浏览器向服务器发起请求行:请求方法,请求URL HTTP协议版本
- 请求行大概意思就是告诉服务器,我需要做上面,比如GET方法,我需要向你拿资源,POST方法通常也就是我需要向服务器提高什么数据,需要注意的就是如果是POST方法,浏览器还需要准备好数据,通过请求体发送给服务器。
- 请求头:把浏览器的基础信息告诉服务器,比如包含了浏览器所使用的操作系统,浏览器的内核信息等,还有请求的域名信息,浏览器的Cookie信息等等。
🤖怎么样,是不是听完这些,懂了一些皮毛了,那接下来看看服务器端是如何处理HTTP的请求吧✍
7. 服务器端处理HTTP请求流程
此时你可以理解成HTTP请求信息终于送到到服务器,接下来服务器会根据请求信息来准备相应的内容啦
7.1 返回请求
服务器处理好后,便把结果数据返回给浏览器,我们来看看放回的数据是怎么样的👇
- 响应行:HTTP协议版本 状态码,通过常见的状态码,就可以知道处理的结果
- 常见状态码:200 表示处理成功。 如果没有找到页面,状态码为404
状态码类型很多,网上很多资料,可以自行查阅,还是推荐两篇比较好的文章:
- 响应头:你可以理解成包含服务器自身的一些信息,比如服务器生成数据的时间,返回数据的类型(HTML,流媒体,JSON,XHTML等等)以及服务器在客户端保存的Cookie等信息
- 响应头中 Cache-Control 字段也很重要,这个涉及到了HTTP缓存,这个字段涵义就是设置缓存资源的时间的
- 发送完响应头后,服务器就可以继续发送响应体的数据,通常,响应体就包含了 HTML 的实际内容。
8.1 断开连接
一般情况下,服务器发送完数据后,就要关闭TCP连接。不过有一种情况比较特殊,我们来看看
http
Connection:Keep-Alive
如果浏览器或者在服务器中加入其头信息如上面的字段的话,TCP连接会仍然保持,这样子浏览器就可以通过同一个TCP连接发送请求,保存TCP连接可以省下去下次请求需要建立连接的时间,提升资源加载速度。
比如,一个 Web 页面中内嵌的图片就都来自同一个 Web 站点,如果初始化了一个持久连接,你就可以复用该连接,以请求其他资源,而不需要重新再建立新的 TCP 连接。
重定向
我们还得聊一聊一种特殊的情况,不过这个情况跟之前提过的状态码 有关,我们大概知道了,服务器返回的状态码不同,会有不同的返回的结果,你肯定遇到过这样子的情况吧:当你在浏览器中打开 baidu.com 后,你会发现最终打开的页面地址是 www.baidu.com ** 这两个URL不一样的原因就是涉及到了重定向**,让我们从一张图片上面看看这种情况吧👇
我们看看响应行返回的状态码301,状态301告诉浏览器,你需要重新转到另外一个网址,需要重定向的地址正式包含在响应头的Location字段中。接下啦,浏览器获取Location字段中的地址,重新导航,这也就是完整的重定向的执行流程。
这解释了为什么输入baidu.com后,最终打开的是www.baidu.com
当然了我只能说考察点太多了,光是http协议就可以问很多的问题,我只是提出一个例子,只有你一步步的去分析并提出一些问题,让疑问带领你去学习,抓住问题的本质学透相关知识点,让你站在一个更高的维度去查看整体框架。
为什么很多站点第二次打开速度会很快?
既然第二次能加快网页的打开速度,肯定第一次加载页面的时候,缓存了耗时的数据
从上面介绍的核心流程来看,比如DNS和页面资源缓存这两块的数据会被浏览器缓存下来。
DNS缓存相对就简单些了,这可以很好看看上面的文章,这里就不展开篇幅介绍了。
浏览器缓存
这个不就是面试常考的吗,聊一聊浏览器的缓存,这里面自然就涉及到常见header中字段
- Cache-Control(重要策略)
- Expires
- Last-modified
- ETag
缓存流程如图:
从上图的第一次请求可以看出,当服务器返回HTTP响应头HTTP响应头给浏览器时,浏览器是通过响应头中的Cache-通过响应头中的Cache-Control字段来设置是否缓存该资源Control字段来设置是否缓存该资源
浏览器缓存的展开的话,又是很大的内容,看看这篇浏览器缓存
总结
浏览器的基本架构(重)
- 最初的浏览器都是单进程的,它们不稳定、不流畅且不安全。
- 之后出现了Chrome创造性地引入了多进程架构,并解决了这些遗留问题。
- 随后Chrome试图应用到更多业务场景,如移动设备、VR、视频等,为了支持这些场景,Chrome的架构体系变得越来越复杂,这种架构的复杂性倒逼Chrome开发团队必须进行架构的重构,最终Chrome团队选择了面向服务架构(SOA)形式。
如何保证⻚面文件能被完整送达浏览器(TCP)?
- 互联网中的数据是通过数据包来传输的,数据包在传输过程中容易丢失或出错。
- IP负责把数据包送达目的主机。
- UDP负责把数据包送达具体应用。
- 而TCP保证了数据完整地传输,它的连接可分为三个阶段:建立连接(三次握手)、传输数据和断开连接(四次挥手)。
为什么很多站点第二次打开速度会很快?
- 浏览器中的HTTP请求从发起到结束一共经历了如下八个阶段
- 浏览器是通过响应头中的Cache-通过响应头中的Cache-Control字段来设置是否缓存该资源Control字段来设置是否缓存该资源