过程:javascript
不会向服务器发送请求,直接从缓存中读取资源,
在chrome控制台的network选项中能够看到该请求返回200的状态码,
而且size显示from disk cache或from memory cache;
复制代码
设置强制缓存的方式:
在响应头设置:
Catch-Control优先级 > Expires优先级
Catch-Control:
好比Cache-Control:max-age=300(秒)
表明在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存
Expires:
好比Expires:Thu,21 Jan 2020 23:39:02 GMT
response header里的过时时间,浏览器再次加载资源时,若是在这个过时时间内,则命中强缓存。
它的值为一个绝对时间的GMT格式的时间字符串;
存在一个缺点:但因为服务端时间和客户端时间可能有偏差,这也将致使缓存命中的偏差,所以如今经常使用这个;
复制代码
协商缓存:向服务器发送请求,服务器会根据这个请求的request
header的一些参数来判断是否命中协商缓存,若是命中,则返回304状态码并带上新的response
header通知浏览器从缓存中读取资源;另外协商缓存须要与cache-control共同使用。;
复制代码
设置协商缓存的方式:
在响应头设置:
Etag优先级 > Last-Modified优先级
Etag:
服务器响应请求时,经过此字段告诉浏览器当前资源在服务器生成的惟一标识(生成规则由服务器决定);
If-None-Match: 再次请求服务器时,浏览器的请求报文头部会包含此字段,后面的值为在缓存中获取的标识。
服务器接收到次报文后发现If-None-Match则与被请求资源的惟一标识进行对比:
a. 不一样,说明资源被改动过,则响应整个资源内容,返回状态码200。
b. 相同,说明资源无意修改,则响应header,浏览器直接从缓存中获取数据信息。返回状态码304.
c. 可是实际应用中因为Etag的计算是使用算法来得出的,而算法会占用服务端计算的资源,
全部服务端的资源都是宝贵的,因此就不多使用Etag了。
Last-Modified: Fri, 22 Jul 2020 01:47:00 GMT
服务器在响应请求时,会告诉浏览器资源的最后修改时间;
if-Modified-Since:
浏览器再次请求服务器的时候,请求头会包含此字段,后面跟着在缓存中得到的最后修改时间。
服务端收到此请求头发现有if-Modified-Since,则与被请求资源的最后修改时间进行对比,
若是一致则返回304和响应报文头,浏览器只须要从缓存中获取信息便可。
从字面上看,就是说:从某个时间节点算起,是否文件被修改了:
a. 若是真的被修改:那么开始传输响应一个总体,服务器返回:200 OK
b. 若是没有被修改:那么只需传输响应header,服务器返回:304 Not Modified
if-Unmodified-Since:
从字面上看, 就是说: 从某个时间点算起, 是否文件没有被修改
若是没有被修改:则开始继续传送文件: 服务器返回: 200 OK
若是文件被修改:则不传输,服务器返回: 412 Precondition failed (预处理错误);
这两个的区别是一个是修改了才下载一个是没修改才下载。
Last-Modified 说好却也不是特别好,由于若是在服务器上,一个资源被修改了,但其实际内容根本没发生改变,
会由于Last-Modified时间匹配不上而返回了整个实体给客户端(即便客户端缓存里有个如出一辙的资源)。
为了解决这个问题,HTTP1.1推出了Etag。
复制代码
强制缓存优先级 > 协商缓存优先级;css
刷新html
用户行为对浏览器缓存的影响
1.地址栏访问,连接跳转是正经常使用户行为,将会触发浏览器缓存机制;
2.F5刷新,浏览器会设置max-age=0,跳过强缓存判断,会进行协商缓存判断;
3.ctrl+F5刷新,跳过强缓存和协商缓存,直接从服务器拉取资源。
复制代码
a. 减小了冗余的数据传递,节省宽带流量
b. 减小了服务器的负担,大大提升了网站性能
c. 加快了客户端加载网页的速度 这也正是HTTP缓存属于客户端缓存的缘由。
复制代码
<script src="test.js" type="text/javascript" defer></script>
复制代码
function loadScript(url, callback) {
const script = document.createElement('script');
script.type = 'text/javascript';
// 处理IE
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
script.onreadystatechange = null;
callback();
}
}
} else {
// 处理其余浏览器的状况
script.onload = function () {
callback();
}
}
script.src = url;
document.body.append(script);
}
// 动态加载js
loadScript('file.js', function () {
console.log('加载完成');
});
复制代码
// 优化前
const el = document.getElementById('test');
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
el.style.padding = '5px';
// 优化后,一次性修改样式,这样能够将三次重排减小到一次重排
const el = document.getElementById('test');
el.style.cssText += '; border-left: 1px ;border-right: 2px; padding: 5px;'
复制代码
let arr1 = [{id: 12, name: 'aa'}, {id: 33, name: 'aa'}];// => {12: {id: 12, name: 'aa', 33: {id: 12, name: 'aa'}};
let arr2 = [{id: 12, age: '18'}, {id: 33,age: '22' }];
复制代码