Skip to content

Commit

Permalink
feat: 浏览器输出
Browse files Browse the repository at this point in the history
  • Loading branch information
jinphic committed Jan 2, 2024
1 parent 8c24bf5 commit 7cd4c82
Showing 1 changed file with 36 additions and 7 deletions.
43 changes: 36 additions & 7 deletions interview/浏览器输入url.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
## 浏览器解析是不是HTTP协议, 浏览器后开启线程进行初始化webview
1. 浏览器解析是不是HTTP协议, 浏览器后开启线程进行初始化webview
2. 通过DNS解析域名的实际IP地址
浏览器缓存1分钟 -> 系统缓存 -> 路由器缓存 -> 运营商 -> 根服务器提供商
3. 检查浏览器是否有缓存
3.1 通过Expires 和 Cache-Control来检查是否命中强缓存
3.1.1 Expires是HTTP1.0的,采用的绝对时间,受系统时间和服务器时间的影响
3.1.2 Cache-Control是Http1.1的,采用的相对时间,优先级也比Expires高,常用字段包括 max_age, no-cache, no-store。
3.1.3 Cache-Control存在的问题:在资源到期之前,服务器资源改变也无法知晓
3.2 如果没有没有命中强缓存,就会进行协商缓存。
3.2.1 协商缓存有两组字段,Last-Modified/If-Modified-since(http1.0)和Etag/If-None-match(http1.1)
3.2.2 服务器会记录Last-Modified最后一次修改的时间,请求的时候带上If-Modified-since,服务器会比比较是否一样。劣势是只要服务器资源变了,无论内容是否变化,都不会命中缓存。
3.2.3 etag是资源的唯一标识,服务器将浏览器传来的if-no-matched跟自己的本地的资源的ETag做对比,如果匹配,则返回304通知浏览器读取本地缓存,否则返回200和更新后的资源。劣势是etag存在计算耗时。
4. 建立HTTP连接,开始TCP三次握手
4.1 客户端随机初始化一个序列号放在TCP报文的头部,然后将SYN标志位设置为1。接着把第一个SYN报文发给服务端,表示把第一个SYN报文发给服务端。此时客户端处于SYN-SENT阶段
4.2 服务端接收到SYN报文后,随机初始化自己的序列号,将此序列号放在TCP首部的序号字段中。接着把SYN 和 ACK标志设置为1 。最后把该报文发给客户端,标识确认应答,此时服务端处于SYN-RCVD状态
4.3 客户端收到服务端报文后,还要发起一个应答报文,将此报文的ACK标志设置为1,确认应答号设置为服务端序列号+1, 这次报文可以携带应用层数据,之后客户端处于ESTABLISHED状态。
4.4 其中起关键左右的是序列号和SYN、ACK标志位
5. 服务器或者CDN响应,设置content-type 为html返回给浏览器
6. 浏览器接受并解析html类型的文件进行渲染

## 通过DNS解析域名的实际IP地址
浏览器缓存 -> 系统缓存 -> 路由器缓存 -> 运营商 -> 根服务器提供商

## 检查是否浏览器是否有缓存
1. 通过Expires 和 Cache-Control来检查是否命中强缓存
2. 如果没有没有命中强缓存,那就发起请求,服务器通过检查Etag和Last-Modified来与服务器确认是否已修改。如果没有更改就返回状态码,浏览器使用本地资源
7. 浏览器渲染流程分为多个阶段:
7.1 HTML解析
在解析过程中,如果遇到css就解析css,但是不会阻塞HTML解析。如果遇到script,就会停止解析,等待script脚本下载和执行完成,因为js的执行可能会影响DOM结构,所以会阻断html解析。
但是script有两个属性 async 和 defer 可以让脚本的下载不阻塞HTML的解析
7.1.1 script async 脚本的下载不会阻塞html的解析,但是当下载完成后会,会暂停解析并先执行脚本,等脚本执行完成后再继续html解析
7.1.2 script defer 脚本的下载不会阻塞html的解析,会等待html解析完成之后,再按脚本的顺序,执行下载好的脚本。
7.1.3 解析完成之后,会得到DOM Tree 和 CSSDOM Tree。
7.2 样式计算,构建渲染树,render tree。在这一过程中,一些预设值会变成绝对值,一些display none的dom树不会出现再渲染树中。
7.3 布局, layout, 这阶段会一次遍历渲染树的每一个节点,计算每个节点的几何信息,例如节点的宽高、相对块的位置等。
7.4 分层,主线程使用一套复杂的策略将布局树进行分层,分层的好处就是某一层改变后,只需处理该层,从而提升效率。滚动条、zindex、transform、opacity等都会影响分层结果。
7.5 绘制,主线程会为每一层单独产生渲染的指令集,用于描述这一层的内容该如何画出来。完成绘制后,主线程将每个图层的绘制信息提交给合成线程,剩下的工作将由合成线程完成。
7.6 分块,合成线程首先对每个图层进行分块,将其划分为更多的小区域
7.7 光栅化, 分块完成后,进入光栅化阶段, 光栅化的结果就是一个一个的像素图。
7.8 画, 指引会标识出每个位图应该画到屏幕的哪个位置。 以及会考虑到旋转、缩放等变形。变形发生在合成线程,与渲染主线程无关,这就是transform效率高的本质原因。

## 建立HTTP连接,开始TCP三次握手
8. 重绘 和 重排
8.1 重绘:重新根据分层信息计算了绘制指令,只要是样式变化了就一定会触发重绘
8.2 重排:重新计算布局树,通过dom操作修改布局树的位置信息,还有获取dom节点的宽高等行为都会触发重排,但是重排不是立刻执行的,会节流和patch。

0 comments on commit 7cd4c82

Please sign in to comment.