从输入URL地址到看到页面,中间都经历了啥
第一步:URL地址解析。
http://www.xxx.com:80/index.html?lx=1&from=weixin#video
http
:即HyperText Transfer Protocol
,超文本传输协议。
https
:即Hypertext Transfer Protocol Secure
,HTTP
+SSL
,更安全的传输协议,经过加密处理。ftp
:即File Transfer Protocol
,文件传输协议,主要用于往服务器上上传内容
和下载内容
。0~65535
之间。
第二步:缓存检查
Expires
: 存储缓存过期的具体时间。
http/1.0
版本的协议中需要设置的字段。Cache-Control
: 存储过多久缓存将过期(单位:秒)或者其它信息。
http/1.1
版本的协议中需要设置的字段。Cache-Control
来设置。Expires
与Cache-Control
字段。
具备在效期的缓存信息
。
html页面
千万不要做强缓存
,以此来保证,即便本地有生效的缓存,但是只要服务器资源更新了,也要从服务器实时获取最新的资源进行渲染!
webpack编译
的时候,我们可以设置一个规则:根据文件的内容,让生成的文件名带唯一hash值
。
main.sae3fd9jk.js
。[name].[hash:8].js
。代码修改
了,每次打包
都会创建不同的文件
出来,而html页面
中导入的也是最新的文件
!强缓存
,就可以保证,服务器资源
一旦更新,我们获取的是最新资源
,而不是本地缓存
!协商缓存
:
协商缓存
是强缓存
的一种补充。
强缓存
还在有效期,即便服务器设置了协商缓存
,那么协商缓存的机制
也不会触发。Last-Modified
:存储该资源在服务器最后一次修改的时间,HTTP/1.0
。ETag
:存储该资源在服务器中最后一次修改的标识(唯一的),HTTP/1.1
。If-Modified-Since
:存储的值是Last-Modified的值。If-None-Match
:存储的值是ETag的值。If-Modified-Since
/If-None-Match
和当前服务器上最新的资源进行对比。
Not-Modified
,浏览器接收到这个状态码,则从本地缓存中获取资源信息进行渲染。Last-Modified
/ETag
值!
实现具备有效期的localStorage存储方案:
/*
//实现具备有效期的localStorage存储方案;
- localStorage.setItem()/localStorage.getItem()/localStorage.removeItem();
- 设置的值,都只能是字符串格式的;
*/
const storage = {
// 存储信息的时候,记录一下存储的时间。
/**
* @param {string} key
* @param {any} value
*/
set(key, value) {
let obj = {
time: +new Date(), //存储时,当前日期的时间戳。
value: value,
};
localStorage.setItem(key, JSON.stringify(obj));
},
// 获取存储信息的时候,判断一下时效性。
/**
* @param {string} key
*/
get(key, expires = 30 * 24 * 60 * 60 * 1000) {
let obj = localStorage.getItem(key);
if (!obj) {
return null; //传递的key压根不存在。
}
let { time, value } = JSON.parse(obj);
if (+new Date() - time > expires) {
// 存储的信息已经地了指定的时效:移除存储的信息、返回null。
storage.remove(key);
return null;
}
return value;
},
// 移除指定信息。
/**
* @param {string} key
*/
remove(key) {
localStorage.removeItem(key);
},
};
无缓存方案:
//无缓存方案:
const query = async function query() {
try {
let result = await axios.get("/api/list", {
params: {
lx: "my",
},
});
console.log(`result-->`, result);
} catch (error) {
console.log(`error-->`, error);
}
};
query()
有缓存方案-本地存储:
/*
//实现具备有效期的localStorage存储方案;
- localStorage.setItem()/localStorage.getItem()/localStorage.removeItem();
- 设置的值,都只能是字符串格式的;
*/
const storage = {
// 存储信息的时候,记录一下存储的时间。
/**
* @param {string} key
* @param {any} value
*/
set(key, value) {
let obj = {
time: +new Date(), //存储时,当前日期的时间戳。
value: value,
};
localStorage.setItem(key, JSON.stringify(obj));
},
// 获取存储信息的时候,判断一下时效性。
/**
* @param {string} key
*/
get(key, expires = 30 * 24 * 60 * 60 * 1000) {
let obj = localStorage.getItem(key);
if (!obj) {
return null; //传递的key压根不存在。
}
let { time, value } = JSON.parse(obj);
if (+new Date() - time > expires) {
// 存储的信息已经地了指定的时效:移除存储的信息、返回null。
storage.remove(key);
return null;
}
return value;
},
// 移除指定信息。
/**
* @param {string} key
*/
remove(key) {
localStorage.removeItem(key);
},
};
//有缓存方案-本地存储:
const query = async function query() {
let result = storage.get("CACHE", 7 * 24 * 60 * 60 * 1000);
if (result) {
//本地是具备有效缓存的,则停止向服务器发送请求。
console.log(`result-->`, result);
return;
}
// 数据没有缓存过:则向服务器发送请求。
try {
let result = await axios.get("/api/list", {
params: {
lx: "my",
},
});
console.log(`result-->`, result);
// 请求成功就:把请求的结果存储到本地。
storage.set("CACHE", result);
} catch (error) {
console.log(`error-->`, error);
}
};
query();
第三步:DNS解析
DNS解析
的缓存时间,大概是1分钟左右。递归查询
在本地缓存中查找DNS解析记录。
www.qq.com 127.0.0.1
www.qq.com
,都相当于在访问127.0.0.1
。http://127.0.0.1:80/index.html
为我开发的页面
。http://www.qq.com
访问的也是本地的这个项目
。迭代查询
到DNS服务器
上查找DNS解析记录
。
想要减少DNS的解析次数,需要把所有的资源部署在相同服务器的相同服务下!
在DNS解析次数增加的情况下,我们可以基于dns-prefetch即DNS预解析,来提高网站的加载速度!
如:
<link rel="dns-prefetch" href="//dss0.bdstatic.com">
<link rel="dns-prefetch" href="//static.360buyimg.com">
…
DNS预解析的原理:
第四步:TCP三次握手
三次握手
。
第一次:客户端向服务器发送一个信息,服务器接收请求。
第二次:服务器向客户端发送一个信息,客户端接收请求。
第三次:客户端向服务器发送一个信息,服务器接收请求。
第五步:客户端和服务器之间的数据通信。
客户端向服务器发送请求,把一些信息传递给服务器。即Request请求阶段。
请求方式
、请求地址
(包括问号传参信息
)、HTTP协议的版本。请求首部
,各种各样的键值对
如token
、Content-Type
、Cookie
、User-Agent
、Authorization…。Request Payload
):请求主体中的数据格式是有限制的。
字符串
:
JSON格式的字符串
:Content-Type:application/json
。urlencoded格式的字符串
:如xxx=xxx&xxx=xxx
,Content-Type:application/x-www-form-urlencoded
。普通字符串
:Content-Type:text/plain
。Content-Type:multipart/form-data
。
Buffer
/二进制
等格式数据。请求主体
中,我们传递的是普通对象
,则浏览器默认会把其变为如"[object Object]"
的普通字符串传递给服务器。
普通对象
,其内部会默认把普通对象
变为JSON格式字符串
,基于请求主体
传递给服务器。服务器
接收客户端的请求
,把客户端需要的信息
返回给客户端
。即Response响应阶段
。
HTTP协议的版本
、HTTP响应状态码
Connection: keep-alive
、Date
-服务器时间
…JSON格式字符串
,但也有可能是其它的格式
(
xml
buffer
HTTP事务:Request
+Response
。
HTTP报文:请求起始行
/请求头
/请求主体
/响应起始行
/响应头
/响应主体
,统称为HTTP报文
!
第六步:TCP四次挥手
第一次挥手
:我把信息给你了,你记得接收哈。第二次挥手
:请求我收到了,你稍等一会吧,我现在去给你准备东西。第三次挥手
:东西已经合你了,你记得接收一下,我这边打算关闭通道了!第四次挥手
):东西我收到了,谢谢,我这边也关闭了。重新地进行
三握四挥,这样太浪费性能和时间了。
请求头
/响应头
中设置Connection:keep-alive
,保持TCP通道的长链接
即可。
HTTP/1.1
版本中,自动就设置了keep-alive长链接机制
,服务器端可以修改长链接的时间或者次数
。第七步:客户端渲染
html
/css
/js
/图片
/数据
等)进行渲染,最后绘制出对应的页面!DOM-Tree
即DOM树
。
当从服务器获取HTML页面后,浏览器会分配GUI渲染线程。自上而下进行解析。
标签
:分配一个新的HTTP网络线程去服务器获取样式资源,同时GUI继续向下渲染!