一线大厂高级前端编写,前端初中阶面试题,帮助初学者应聘,需要联系微信:javadudu

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

前言

关于 《地址栏输入URL 到页面展现经历了哪些过程》 这个问题是一个老生常谈了,无论是在面试中,还是说工作处理问题,都会用的上,最近在研究相关的内容,所以就我的知识进行了一个梳理,后面理解深入还会补充,或者也可以在评论区留言,我会看到的哦!

简单概括性的回答:

主要是两大部分工作,一部分是网络部分,一部分是浏览器渲染部分

一、网络部分

总结概括如下:

1. 解析url并且判断其合法性 
2. DNS解析url到指定的ip
3. 建立TCP连接(3次握手)
4. 发送HTTP请求(请求行/头/体)(查询http缓存阶段见下图)
5. 服务器处理收到的请求,将数据返回浏览器
6. 浏览器收到HTTP响应
7. 浏览器解析并渲染页面
8. 关闭TCP连接

关于请求的步骤如下图:

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

下面就上述步骤中的一些需要重点理解的点,来展开讲讲。

1. 解析url并且判断其合法性

浏览器会先进行url解析,会判断输入的是一个合法的url还是一个待搜索的关键词

不合法:如果输入的 URL 中的协议或者主机名不合法,将会把地址栏中输入的内容传递给搜索引擎。

合法:检验地址合法后,浏览器会检查URL中是否出现了非法字符,如果存在非法字符,则对非法字符进行转义后再进行下一过程。


2. DNS解析url的过程

查找过程如下:

  • 本地电脑检查浏览器缓存中有没有这个域名对应的解析过的ip地址,如果缓存有,解析结束

  • 缓存中没有数据,查找操作系统缓存中是否有这个域名对应的解析结果

  • 前两个都没有,操作系统会把这个域名发送给这个本地DNS服务器

  • 本地没有,去根DNS服务器请求解析

  • 根服务器返回给本地一个顶级DNS服务器地址,拿到后向顶级DNS服务器发送解析请求

  • 接受请求查询并返回此域名对应的Name Server 域名服务器的地址

  • Name Server根据映射关系表找到目标ip返回该域名对应的IPTTL本地DNS服务器会缓存一份这个域名和IP的对应关系,缓存时间由TTL值控制。

  • 把解析的结果返回给本地电脑,本地电脑根据TTL值缓存在本地系统缓存中

迭代查询和递归查询的区别:

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

更细节的解释


3. 关于TCP连接的次握手和次挥手

  1. 从最开始双方都处于CLOSED关闭状态。

  2. 客户端主动请求建立连接,发送 SYN到服务端 , 自己变成了SYN-SENT状态。

  3. 服务端接收到请求,针对客户端的SYN的确认应答,返回SYNACK(对应客户端发来的SYN),并请求建立连接,自己变成了SYN-REVD

  4. 客户端收到服务端的请求,对服务端SYN的确认应答,并发送ACK给服务端,自己变成了ESTABLISHED状态;

  5. 服务端收到ACK之后,也变成了ESTABLISHED状态。

另外需要提醒你注意的是,SYN 是需要消耗一个序列号的,下次发送对应的 ACK 序列号要加1,因为
凡是需要对端确认的,一定消耗TCP报文的序列号。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

参考文章


4. 握手为什么是三次握手不是四次

三次握手的目的是确认双方发送接收的能力,那四次握手可以嘛?

当然可以,100 次都可以。但为了解决问题,三次就足够了,再多用处就不大了。


5. 三次握手过程中可以携带数据么?

首先说答案:第三次握手的时候,可以携带。前两次握手不能携带数据。

如果前两次握手能够携带数据,那么一旦有人想攻击服务器,那么他只需要在第一次握手中的 SYN 报文中放大量数据,那么服务器势必会消耗更多的时间和内存空间去处理这些数据,增大了服务器被攻击的风险。第三次握手的时候,客户端已经处于ESTABLISHED状态,并且已经能够确认服务器的接收、发送能力正常,这个时候相对安全了,可以携带数据。

6. 挥手为什么是四次三次不行吗?

答案:不可以

是因为挥手要保证双方都确认断开。所以每一步的反馈就必须干净利落,而不能像握手一样耦合在一起,例如:客户端申请断开连接后,服务端返回确认,此时只能代表客户端不会再向服务器发送信息,但不代表它不可以接收信息。所以如果双方都要断开,就要对每一步的请求进行确认,而不能耦合在一起,所以三次不可以。


7. 在发送http请求时会先进行缓存查询,那么什么是http缓存?

http缓存指的是: 当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有要请求资源的副本,就可以直接从浏览器缓存中提取而不是从原始服务器中提取这个资源。

常见的http缓存只能缓存get请求响应的资源,对于其他类型的响应则无能为力,所以后续说的请求缓存都是指get请求

分类:

  • 根据是否需要再请求:可分为强制缓存和协商缓存,强制缓存如果生效,不需要再和服务器发生交互,而协商缓存不管是否生效,都需要与服务端发生交互;
  • 根据是否可以被单个或者多个用户使用来分类,可分为私有缓存和共享缓存

在强制缓存时:cache-control的优先级要高于expirse,原因如下:
  • expirse相对于服务器时间的,cache-controlmax-age是相对于上次返回请求结果的时间
在协商缓存时,ETag的优先级是高于Last-Modifined,原因如下:
  • 某些服务器不能精确得到文件的最后修改时间, 这样就无法通过最后修改时间来判断文件是否更新了。

  • 某些文件的修改非常频繁,在秒以下的时间内进行修改 Last-Modified只能精确到秒

  • 一些文件的最后修改时间改变了,但是内容并未改变。 我们不希望客户端认为这个文件修改了。

关于缓存的细节如下图:

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

二、浏览器渲染部分

渲染过程是指将我们的html css js的代码通过复杂运算,转换成像素展示到屏幕上。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

前提是先通过浏览器的网络线程去获取HTML,当收到HTML文档后,会生成一个渲染任务,交由渲染主线程的消息队列。 然后在事件机制的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程。

渲染流程分为多个阶段:

每个阶段性任务都会有输出,作为下一步任务的输入。

总结概括:

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

  • html解析:解析整个html内的所有内容,输出DOMCSSOM
  • 样式计算:合并DOMCSSOM树,计算得到初步的样式
  • 布局:将render树通过计算相对大小、位置等信息,得到layout
  • 分层:在这一步将得到最终样式的树进行分层处理,方便后面有操作或更新时的最小影响
  • 绘制:将已经分层的内容生成指令集,每个指令代表本层是如何进行绘制,到此渲染主线程任务结束
  • 分块:将已经分层好的内容进行颗粒度再小的分块,此时交由合成线程,合成线程会开辟多个线程同时进行
  • 光栅化: 在此步骤将我们已经分块好的内容交由GPU进行光栅化,这一步会得到一个一个的位图块儿
  • :将我们得到的一堆位图块进行最终合并画到屏幕上

1. 解析htmlcss

先将字符串解析转换成对象结构,方便后续操作。在这一步会产生两棵树:解析html 生成 dom树 ,解析CSS生成CSSOM树(包含有内部样式表、外部样式表,内联样式表,浏览器默认样式表等内容 )

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

什么是预解析?

浏览器在开始解析前,会启动一个预解析道线程,率先下载HTML中的外部CSS文件和外部的JS文件。预解析线程快速浏览,找到CSS,通知网络线程去下载CSS,下载完去交给预解析线程去解析,解析完再回给渲染主线程生成CSSOM树。主要目的:提高整体解析效率。

CSS会不会阻塞html解析?

如果主线程解析到link的位置,此时外部的CSS文件还没有下载解析好,主线程不会等待,继续解析后续的HTML,当CSS解析完成后,直接交给主线程取生成CSSOM树即可。这是因为下载和解析CSS的工作是在预解析线程中进行的。这就是CSS不会阻塞HTML解析的根本原因。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

CSS会不会阻塞渲染?

因为当css树没有构建完成,页面是不会渲染到浏览器的,需要将它尽早、尽快地下载到客户端,以便缩短首次渲染的时间,尽量减少样式嵌套,如果时间过长会导致白屏。

CSS优化方案

  • 将css文件放在页面最上面

  • 减少使用 * 通配符

  • 尽量减少页面重排、重绘

  • 尽量少的使用@import,而是使用link, link是同步加载

  • 删除冗余代码

  • 如果值为0,可以不写单位

  • 减少嵌套不超过3层,可以尽量多的使用继承


js会不会阻塞html解析?

如果主线程解析到script位置,会停止解析html,转而等待js文件下载好,并将全局代码解析执行完成后,才能继续解析html。这是因为js代码的执行过程可能会修改当前的DOM树,所以DOM树的生成必须暂停,这就是js会阻塞html解析道根本原因。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

js优化方案:

  • js 放到页面底部,当html 解析完再去解析js

  • 异步加载:设置defer,当遇到defer标识会先进行下载但不执行,等html渲染完成后再执行 


图片会不会阻塞渲染?

图片不会阻塞渲染,因为浏览器有一个单独的渲染进程去渲染图片,是并行的,所以不会阻塞渲染。


2. 进行样式计算,合成render

主线程会遍历得到的DOM 树,结合CSSOM树,去计算样式,计算过程中有些样式会变化,去得到每个元素的最终样式,称之为 Computed Style。在这一过程中,很多预设值会变成绝对值,比如 red 会变成 red(255,0,0) ,相对单位会变成绝对单位,比如em 会变成px

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?


3. 布局

布局阶段会依次遍历DOM树的每一个节点,计算每个节点的几何信息,例如节点的宽高、相对包含块的位置。大部分时候,DOM树和布局树并非一一对应。布局完成后会得到布局树。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

Dom树和Layout树为什么不是一一对应的?

比如display:none的节点没有任何信息,因此不会生成布局树;又比如使用了伪类选择器,虽然DOM树中不存在这些伪元素节点,但他们拥有几个信息,所以会生成到布局树中。还有匿名行盒和匿名块盒等待都会导致DOM树和布局树无法一一对应。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?


4. 分层:Layer

主线程会使用一套复杂的策略对整个布局树中进行分层,每个层面可以单独进行绘制。分层的好处在于,将来某个层次改变后,仅会对该层进行后续处理,从而提升效率。像滚动条、堆叠上下文、transformopacity z-index 等样式可能会影响分层结果,也可以通过设置will-change 属性更大程度的影响分层结果.

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

will-change:transform

一定是效率出现了问题,调整后发现是分层导致的卡顿,不要滥用,这个样式会告诉浏览器可能会发生变化


5. 绘制

会先去生成绘制的指令集合,用于描述这一层的内容如何画出来,例如:先后顺序,位置确定等等。主线程任务会停止,然后交给其他线程来操作。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?


6. 分块

完成绘制后,主线程将每个图层的绘制信息提交给合成线程,剩余工作交给合成线程完成。合成线程首先将每个图层进行分块,将其划分为更多的小区域,分块会将每一层分为多个小的区域,将工作交给多个线程同时进行

它会从线程池中拿取多个线程来完成工作

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?


7. 光栅化

合成线程会将块信息交给GPU进程,以极高的速度完成光栅化,GPU 进程会开启多个线程来完成光栅化,并且优先处理靠近视口区域的块。光栅化的结果,就是一块一块的位图

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

8. 画

最终画在浏览器屏幕上

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?


三、和整个过程相关的一些扩展知识点:

1. 什么是浏览器的默认样式?

p div 为什么独占一行,是因为浏览器给它设置了默认样式,display:block ,所以它才独占一行,惊不惊喜,意不意外?原来这么简单

浏览器的源码,默认样式的链接地址


2. 什么是行盒?什么是块盒?

内容必须在行盒中,如果在p 元素中有一个元素,没有包行盒,那就会自动给它补充一个匿名行盒。已经早就没有行元素和块元素的说法了,因为元素的样式是由css来决定的而不是html的元素,行盒和块盒不能相邻。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?


3. 为什么要使用 http 缓存?

  • 减少了冗余的数据传输,节省了网费。
  • 缓解了服务器的压力, 大大提高了网站的性能
  • 加快了客户端加载网页的速度

4. 为什么浏览器会有兼容性问题?

浏览器的兼容性?

源于浏览器的渲染引擎,渲染引擎决定了浏览器如何显示网页的内容以及页面的格式信息。不同的浏览器内核对网页编写语法的解析也有不同,因此同一网页在不同的内核的浏览器里的渲染(显示)效果也可能不同,这就出现了浏览器兼容性问题。

常见的浏览器内核:

  • Trident内核IE360、搜狗浏览器等。

  • Webkit内核SafariChrome等。

扩展知识点:【 ChromeBlinkWebKit的分支,V8Blinkjs引擎】

关于js兼容性问题的解决

使用babel 来转译,因为它是可以将最新版本的js 语法转为最老的js 语法,让更多的浏览器可以识别

关于css 兼容性问题的解决

在样式的头部加浏览器的前缀:例如 -webkit

关于html 兼容性问题:

可以通过设置<!DOCTYPE html>字段来解决,如果不写,各个浏览器会使用自己的怪异模式去解析,不是我们想要的结果,写了是让浏览器用统一方式去处理


5. 什么是重排reflow?

reflow 的本质就是重新计算layout 树。当局部或者整体布局发生改变,例如:新增或者删除dom元素,改变marginpadding、 字体大小等等。可能会影响到布局时,就会启动重新计算样式,重新生成布局,重新排列元素。相当于从计算样式向后所有的步骤都要走一遍,所以会比较耗费性能

为了避免连续的多次操作导致布局树反复计算,浏览器会合并这些操作,当js 代码全部完成后再进行统一计算。所以,改动属性造成的reflow是异步完成的。也同样因为如此,当js 获取布局属性时,就可能无法获取到最新的布局信息。浏览器为了避免这个情况的产生,读取样式会立即执行reflow

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

6. 什么是重绘 repaint?

repaint 的本质就是重新根据分层信息计算了绘制指令。当某些元素的外观被改变,就需要重新计算。计算样式和绘制阶段之后的阶段都要重新过一遍。

重绘不一定导致重排,但重排一定会导致重绘。重排的开销要远远大于重绘,会破坏用户体验,并且让UI展示非常迟。所以我们要尽量减少页面重排次数。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

7. 为什么transfrom 的效率高?

因为transform 改动样式后,就只影响了计算样式和最后画的步骤,中间很多步骤都可以跳过,所以它的效率要高。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

如果transform来配合 animation一起使用,效率会更高,中间步骤直接都跳过,只影响最后画的步骤

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?

8. 浏览器遇到无法解析的css 会做什么?

浏览器遇到无法解析的css 会做什么

9. 关于几种刷新后对缓存的影响?

地址栏回车:

浏览器发起请求,按照正常流程,本地检查是否过期,然后服务器检查新鲜度,最后返回内容。

点击刷新按钮或者按 F5

浏览器直接对本地的缓存文件过期,但是会带上If-Modifed-SinceIf-None-Match,这就意味着服务器会对文件检查新鲜度,返回结果可能是 304,也有可能是 200

用户按 Ctrl+F5强制刷新:

浏览器不仅会对本地文件过期,而且不会带上 If-Modifed-SinceIf-None-Match相当于之前从来没有请求过,返回结果是 200

链接

9. 什么时候会断开TCP的连接

不同的协议断开的标准不同,但都是一定程度上避免浪费资源,因为保持连接对于服务器来说也是需要占用资源的

  • http1: 如果没有设置keep-alive ,一个请求发送过去,服务端响应后,就会立即断开

  • http1.1 内部自带keep-alive,短时间内是不用重复连接的,keep-alive会有一个过期时间,当超过设置时间会自动断开

  • http2 是支持多路复用的,所以和请求否响应无关,它的断开标准通常是当双方服务器在30秒内如果没有再发生交互,即断开连接。

【浏览器】关于地址栏输入URL到页面展现经历了哪些过程?


本期先分享到这里,后面有浏览器相关的内容我会再做补充,欢迎各位掘友收藏关注哈!!!

原文链接:https://juejin.cn/post/7240333779221987384 作者:玖月晴空

(0)
上一篇 2023年6月4日 上午10:26
下一篇 2023年6月4日 上午10:37

相关推荐

发表评论

登录后才能评论