
从 URL 输入到页面渲染发生了什么:
DNS 查询TCP 连接HTTP 报文浏览器渲染断开连接
DNS 查询
当我们从浏览器地址输入内容,浏览器会根据我们输入的信息进行分析,如果是关键字则会使用默认配置的搜索引擎来查询,如果输入的是域名,就会通过DNS去查询对应的IP地址。
DNS 查询过程:浏览器会去搜索自身的缓存,如果存在就会终止域名解析。如果没有在缓存中找到对应的条目,那么就会尝试读取操作系统的HOST文件,看是否存在对应的映射关系,存在解析到此为止。(PS:很多时候当我们去访问一个网址响应非常慢的时候,这里就可以用上了!) 如果在本地HOST文件不存在对应的映射关系,则查找本地DNS服务器,存在完成解析反之它就会向根服务器发起请求,进行递归查询。
TCP 连接
浏览器得到对应的IP地址,并向该IP地址发起请求建立TCP连接。
- TCP 连接全过程可以简单阐述为三次握手与四次挥手
- TCP 三次握手:
- 客户端发送一个带 SYN=1,Seq=X 的数据包到服务器端口(第一次握手,由浏览器发起,告诉服务器我要发送请求了)
- 服务器发回一个带 SYN=1, ACK=X+1, Seq=Y 的响应包以示传达确认信息(第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧)
- 客户端再回传一个带 ACK=Y+1, Seq=Z 的数据包,代表“握手结束”(第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧)
引入问题:
TCP 为什么要握三次手,为什么不是两次 ?
- 为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤
- 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认
HTTP 报文
TCP 三次握手结束后,开始发送接收 HTTP 报文。这里的报文指的分别是请求报文与响应报文
- 请求报文
请求报文如下:分为四部分请求行,请求头部,空行与请求体。
- 响应报文
响应报文同请求报文一样
对于这个阶段我们可以做什么?
- CDN
CDN是什么?
CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术
CDN是如何做的?
关于CDN缓存,在浏览器本地缓存失效后,浏览器会向CDN边缘节点发起请求。类似浏览器缓存,CDN边缘节点也存在着一套缓存机制。CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的 Cache-control: max-age 的字段来设置CDN边缘节点数据缓存时间。
当浏览器向CDN节点请求数据时,CDN节点会判断缓存数据是否过期,若缓存数据并没有过期,则直接将缓存数据返回给客户端;否则,CDN节点就会向服务器发出回源请求,从服务器拉取最新数据,更新本地缓存,并将最新数据返回给客户端。 CDN服务商一般会提供基于文件后缀、目录多个维度来指定CDN缓存时间,为用户提供更精细化的缓存管理。
- 浏览器缓存

浏览器向服务器请求资源时,先会去判断是否命中强缓存, 再去判断是否命中协商缓存。
强缓存: 浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。这里的 header 中的信息指的是 expires 和 cahe-control.
- Expires: 该字段是 http1.0 时的规范,它的值为一个绝对时间的 GMT 格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。
- Cache-Control:Cache-Control 是 http1.1 时出现的 header 信息,主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。cache-control 除了该字段外,还有下面几个比较常用的设置值:
- no-cache:需要进行协商缓存,发送请求到服务器确认是否使用缓存。
- no-store:禁止使用缓存,每一次都要重新请求数据。
- public:可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器。
- private:只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。
- Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。
协商缓存: 当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中缓存。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。这里的 header 中的信息指的是 Last-Modify/If-Modify-Since 和 ETag/If-None-Match.
- Last-Modify/If-Modify-Since:
浏览器第一次请求一个资源的时候,服务器返回的 header 中会加上 Last-Modify,Last-modify 是一个时间标识该资源的最后修改时间。
当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since,该值为缓存之前返回的 Last-Modify。服务器收到 If-Modify-Since 后,根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回 304,并且不会返回资源内容,并且不会返回 Last-Modify。
缺点: 短时间内资源发生了改变,Last-Modified 并不会发生变化。
周期性变化。如果这个资源在一个周期内修改回原来的样子了,我们认为是可以使用缓存的,但是 Last-Modified 可不这样认为,因此便有了 ETag。
- ETag/If-None-Match:
与 Last-Modify/If-Modify-Since 不同的是,Etag/If-None-Match 返回的是一个校验码。ETag 可以保证每一个资源是唯一的,资源变化都会导致 ETag 变化。服务器根据浏览器上送的 If-None-Match 值来判断是否命中缓存。
与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。
Last-Modified 与 ETag 是可以一起使用的,服务器会优先验证 ETag,一致的情况下,才会继续比对 Last-Modified,最后才决定是否返回 304。
浏览器渲染
浏览器拿到响应文本 HTML 后,解析相关的文件,把 HTML 转换成对应的 DOM 树,把 CSS 解析成 CSS 规则树,然后把DOM树和CSS规则树结合起来构建成 Render 树,浏览器通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸来构建布局。通过遍历呈现树,并调用呈现器的“paint”方法然后绘制在页面上。
对于这个阶段我们可以做什么?
- 回流
何时发生回流:也就是浏览器在视图渲染之前,计算元素需要在页面呈现的位置,这个阶段就是回流。
回流是如何触发的:
- 调整窗口大小
- 改变字体
- 增加或者移除样式表
- 内容变化,比如用户在 input 框中输入文字, CSS3 动画等
- 激活 CSS 伪类,比如 :hover
- 操作class属性
- 脚本操作DOM
- 计算 offsetWidth 和 offsetHeight 属性
- 设置 style 属性的值
- 重绘
回流是如何触发的:当视图中某个元素视觉效果变化引起的重新绘制。比如 color 或者 background 等这些不会改变元素大小位置的属性。
重绘不一定会触发重绘,但是回流必定会触发重绘
参考资料
萧萧冷(TCP 为什么三次握手而不是两次握手) 链接地址:https://blog.csdn.net/lengxiao1993/article/details/82771768
null仔(实践这一次,彻底搞懂浏览器缓存机制) 链接地址:https://segmentfault.com/a/1190000017962411