从url输入到页面呈现发生了什么
1.URL解析
encodeURI / decodeURI
对整个URL的编码:处理空格/中文
let url = "http://https://blog.csdn.net/api/ ?lx=1&name=科比&from=http://www.baidu.com/";
console.log(encodeURI(url));
encodeURIComponent / decodeURLComponent
主要对传递的参数信息编码
let url = `http://https://blog.csdn.net/api/ ?lx=1&name=${encodeURIComponent(
"科比"
)}&from=${encodeURIComponent("http://www.baidu.com/")}`;
console.log(url);
2.缓存检查
先检测是否存在强缓存
- 有且未失效 走强缓存
- 如果没有 或者失效 检测是否有协商缓存
- 有 走协商缓存
- 没有 获取最新数据
缓存位置
Memory Cache:内存缓存
Disk Cache: 硬盘缓存
打开网页:查找disk cache中是否有匹配 如果有则使用 如果没有则发送网络请求
普通刷新(F5):因TAB(页面)没关闭 因此memory cache是可用的 会被优先使用 其次才是disk cache
强制刷新(Ctrl + F5):浏览器不适用缓存 因此发送的请求头部均使用Cache-control: no-cache 服务器直接返回200和最新内容
强缓存
Expires / Cache-Control
强缓存的性能比协商缓存好
浏览器对于强缓存的处理:根据第一次请求资源时返回的响应头来确定的
- Expires:缓存过期时间 用来指定资源到期的时间(HTTP/1.0)
- Cache-Control:cache-control: max-age=2592000第一次拿到资源后的2592000秒内(30天) 再次发送请求 读取缓存中的信息(HTTP/1.1)
- 两者都存在的话:Cache-Control优先级高于Expires
html页面一般不做强缓存
- 每一次html的请求都是正常的HTTP请求
强制缓存有问题
如果服务器文件更新了 但是本地还有缓存
这样不就拿不到最新的信息了吗
- 服务器更新资源后 让资源名称和之前不一样 这样页面导入全新的资源index.aaa.js变为index.bbb.js(webpack的hash name)
- 当文件更新后 我们在html导入的时候 设置一个后缀 设置一个(时间戳)
- 使用协商缓存
协商缓存
Last-Modified / ETag
Last-Modified 只能精确到秒
如果我们在1秒内 完成了资源的返回 和新资源的更新 这样就识别不出来
所以有了ETag
不管你有没有缓存 浏览器都会携带缓存的标识向服务器发请求 由服务器来校验当前资源有没有更新 没更新 返回304 通知客户端读取缓存信息 之后浏览器从本地中获取内容进行渲染 更新过 返回200及最新资源信息 以及Last-Modified / ETag 之后浏览器直接渲染 并且把最新的结果和标识缓存到本地
协商缓存与强缓存的区别:
协商缓存总会和服务器协商 所以一定要发HTTP请求
第一次向服务器发送请求
协商缓存没有
向服务器发送请求(没有传递任何标识)
服务器收到请求准备内容
Last-Modified:资源文件最后更新的时间
ETag:记录的是一个标识(也是根据资源文件更新生成的 每一次资源更新都会重新生成一个ETag)
客户端拿到信息后渲染
把信息和标识缓存到本地
第二次发请求
If-Modified-Since = Last-Modified值
If-None-Match = ETag值
给服务器
服务器根据标识判断文件是否更新
数据存储
3.DNS解析
递归查询
每一次DNS解析时间预计在20-120毫秒
- 减少DNS请求次数 (一个页面中尽可能少用不同的域名:资源都放在相同的服务器上【项目中往往会把不同的资源放到不同的服务器上】)
- DNS预获取(DNS Prefetch)
DNS预获取实现
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="//url1地址"/>
<link rel="dns-prefetch" href="//url2地址"/>
<link rel="dns-prefetch" href="//url3地址"/>
服务器拆分优势
- 资源的合理利用
- 抗压能力加强
- 提高HTTP并发
4. TCP三次握手 建立连接通道
seq序号 用来标识从TCP源端向目的端发送的字节流 发起方发送数据时对此进行标记
ack确认序号 只有ACK标志位为1时 确认序号字段才有效 ack=seq + 1
标志位:
- ACK:确认序号有效
- RST:重置连接
- SYN:发起一个新的连接
- FIN:释放一个连接
三次握手为什么不用两次 或 四次
TCP作为一种可靠传输控制协议 其核心思想:既要保证数据可靠传输(两次不行) 又要提高传输的效率(四次不行)
5.数据传输
6.TCP四次挥手
为什么是四次挥手
原因 第一次挥手的时候发送了FIN包 服务器接收到以后 表示客户端不在发送数据了 但还能接收数据 这时服务器先向客户端发送确认包 并且确认自己是否还有数据没有发送给客户端 这个确认的阶段是CLOSE-WAIT 所以在终止等待(CLOSE-WAIT)的开始和结束都需要个发送一个包 状态开始时向客户端发送的包是确认收到来自客户端的FIN包 状态结束时向客户端发送过的是确认数据已经完整发送 所以是四次挥手
Connection: keep-alive 保证通道建立完成后 可以不关闭
HTTP1.0 需要自己手动设置
HTTP1.1版本后 规范 默认就是这样的