当前位置: 首页 > news >正文

浏览器缓存机制分析

浏览器缓存

基础概念

缓存无处不在,有客户端缓存,服务端缓存,代理服务器缓存等等。和前端相关的缓存一般都是指http缓存,也就是浏览器缓存。

就是说ajax请求之后,会把请求的url和返回的响应结果保存在缓存中,当下一次调用ajax发送相同的请求时,浏览器会从缓存中把数据取出来,这是为了提高页面的响应速度和用户体验,什么时候会出现这个现象呢,就是要这两次的请求url和请求参数完全一样的时候,浏览器就不会与服务器交互。

缓存的优缺点

优点

现在说一下缓存的好处,好处显而易见嘛,就是说请求一些静态资源,js,css,图片这些,不会变化的资源,请求会变得更快,加快了客户端加载网页的速度,提高了页面的响应速度,也减少了冗余数据的传递,节省了网络带宽流量,减少服务端的负担,大大提高了网站性能。

缺点

但是缺点也显而易见,客户端和服务端交互的时候,服务端的数据虽然变了,但是页面缓存没有改变,对于相同的url,ajax提交过去以后,浏览器是从缓存中拿数据,这种情况肯定是不被允许的。

那么什么时候会触发缓存呢,在这之前先说一下缓存机制吧。

缓存机制

缓存一般分为强制缓存协商缓存,接下来将分别介绍一下这两个缓存机制。

强制缓存

就是缓存中已经有了请求数据的时候,客户端直接从缓存中获取数据,只有当缓存中没有请求数据的时候,客户端才会从服务端拿取数据。

协商缓存

也成为对比缓存,就是说客户端会从缓存中获取到一个缓存数据的标识,根据这个标识会请求服务端验证是否失效,如果没有失效,服务端会返回304,这时候客户端就直接从缓存中取数据,如果失效了,服务端会返回新的数据。

这两种缓存机制可以同时存在,不过强制缓存的优先级高于协商缓存。

现在我们简单的了解了一下缓存机制的原理,该说一下什么时候会触发缓存,服务端是如何判断缓存是否失效呢?大家都知道,发送请求的时候会有请求数据和响应数据,这个被称为报文,报文中包含首部header和主体部分body。与缓存相关的规则信息就包含在header中。body中的内容就是http请求真正要传输的数据。举个http报文的头部例子

1114764-20171218110148521-735904414.png

现在我们对报文中出现的与缓存有关的信息分析一下

强制缓存

服务器响应的header中会用两个字段来表明,Expires和Cache-Control。

Expires

Expires的值是服务端返回的数据到期时间。当再次请求时的请求时间小于返回的此时间,则直接使用缓存数据,但是因为客户端和服务端的时间可能有误差,所以这个缓存命中可能会有误差,另一方面,expires是http1.0的产物,所以现在大多数都使用Cache-Control

Cache-Control

Cache-Control有很多产物,不同的属性代表的意义不同。

private: 客户端可以缓存

public: 客户端和服务器可以缓存

max-age=t:缓存内容在t秒后失效

no-cache:需要使用协商缓存来验证缓存数据

no-store:所有内容不使用缓存

协商缓存

协商缓存需要判断是否可以用缓存,浏览器第一次请求数据的时候,服务器会将缓存标识与数据一起响应给客户端,客户端将他们备份到缓存中,再次请求时,客户端会将缓存中的标识发送给服务器,服务器根据此标识判断是否失效,如果没有失效,服务端返回304状态码,浏览器拿到此状态吗就可以直接使用缓存数据了。对于协商缓存来说,缓存标识很重要,对于理解协商缓存,这是重点。

接下来介绍一下协商缓存的缓存方案

Last-Modified

Last-Modified

服务端在响应请求时,会返回资源的最后修改时间

If-Modified-Since

客户端再次请求服务端的时候,请求头会包含这个字段,后面跟着在缓存中获取的资源的最后修改时间。服务端收到请求发现此请求头中有If-Modified-Since字段,会与被请求资源的最后修改时间进行对比,如果一致则会返回304和响应报文头,浏览器从缓存中获取数据即可。从字面上看,就是说从某个时间节点开始看,是否被修改了,如果被修改了,就返回整个数据和200 OK,如果没有被修改,服务端只要返回响应头报文,304 Not Modified.

If-Unmodified-Since

和If-Modified-Since相反,就是说从某个时间点开始看,是否没有被修改.如果没有被修改,就返回整个数据和200 OK,如果被修改了,不传输和返回412 Precondition failed (预处理错误)

If-Modified-Since和If-Unmodified-Since区别就是一个是修改了返回数据一个是没修改返回数据。

Last-Modified也有缺点,就是说服务端的资源只是改了下修改时间,但是其实里面的内容并没有改变,会因为Last-Modified发生了改变而返回整个数据,为了解决这个问题,http1.1推出了Etag

Etag

Etag

服务端响应请求时,通过此字段告诉客户端当前资源在服务端生成的唯一标识(生成规则由服务端决定)

If-None-Match

再次请求服务端的时候,客户端的请求报文头部会包含此字段,后面的值是从缓存中获取的标识,服务端接收到报文后发现If-None-Match则与被请求的资源的唯一标识对比。如果相同,说明资源不用修改,则响应header,客户端直接从缓存中获取数据,返回状态码304,如果不同,说明资源被改过,返回整个数据,200 OK。

但是实际应用中由于Etag的计算是使用算法计算出来的,而算法会占用服务端的资源,所有服务端的资源都是宝贵的,所以很少使用Etag。

现在顺便说一下不同的刷新的请求执行过程哈

  1. 浏览器直接输入url,回车
    浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存中拿(最快)
  2. F5
    告诉浏览器,去服务端看下文件是否过期了,于是浏览器发了一个请求带上If-Modified-Since
  3. Ctrl+F5
    告诉浏览器,先把缓存删了,再去服务端请求完整的资源文件过来,于是浏览器就完成了强制更新的操作

如果不想使用缓存怎么办呢,接下来说一下解决方法

解决方法

  1. 在ajax发送请求前加上 xmlHttpRequest.setRequestHeader(“Cache-Control”,”no-cache”);
  2. 在服务端加 header(“Cache-Control: no-cache, must-revalidate”);
  3. 在ajax发送请求前加上 xmlHttpRequest.setRequestHeader(“If-Modified-Since”,”0″);
  4. 在 Ajax 的 URL 参数后加上 "?fresh=" + Math.random(); //当然这里参数 fresh 可以任意取了
  5. 第五种方法和第四种类似,在 URL 参数后加上 "?timestamp=" + new Date().getTime();
  6. 用POST替代GET:不推荐
  7. jQuery提供一个防止ajax使用缓存的方法:
<script type="text/javascript" language="javascript">
     $.ajaxSetup ({ 
           cache: false //close AJAX cache 
      }); 
</script>
  1. 修改load 加载的url地址,如在url 多加个时间参数就可以:
function loadEventInfoPage(eventId){

    $.ajaxSetup ({ 
       cache: true // AJAX cache  下面加上时间后load的页面中的js、css图片等都会重新加载,   

         //加上这句action会重新加载,但是js、css、图片等会走缓存 
    }); 
    $("#showEventInfo").load(ctx + "/custEvents/viewEvent.action",  {"complaint.Id":eventId, "tt":(new Date()).getTime()},function(){}) 
}

9.设置html的缓存

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">    
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">    
<META HTTP-EQUIV="Expires" CONTENT="0">

相关文章:

  • centos7部署redis
  • Code First开发系列之领域建模和管理实体关系
  • ImageMagick 打水印支持透明度设置
  • 吴颖二:12.19 年关将在翻仓已“迫不及待”你准备好了吗
  • 第二天个人总结
  • SQL Server复制入门(一)----复制简介
  • 系统架构师-基础到企业应用架构-系统建模[上篇]
  • 设计模式之缺省适配模式
  • 【Excle数据透视表】如何按照地区交替填充背景颜色
  • activeMq之hello(java)
  • 第2周第3课:chmod、chown、umask、lsattr/chattr
  • 罗森伯格成功部署印度某著名港口光纤基础设施
  • 【css】设置div位于浏览器的最底层,离用户最远
  • 经济金融领域简单数学建模和分析:MATLAB成本曲线方程和销售收入直线方程
  • 码子杂记
  • 【知识碎片】第三方登录弹窗效果
  • 4. 路由到控制器 - Laravel从零开始教程
  • ECS应用管理最佳实践
  • ERLANG 网工修炼笔记 ---- UDP
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • happypack两次报错的问题
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • Zepto.js源码学习之二
  • 初识 beanstalkd
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 搭建gitbook 和 访问权限认证
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 工作手记之html2canvas使用概述
  • ------- 计算机网络基础
  • 将回调地狱按在地上摩擦的Promise
  • 如何合理的规划jvm性能调优
  • 深入浏览器事件循环的本质
  • 想使用 MongoDB ,你应该了解这8个方面!
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • # 透过事物看本质的能力怎么培养?
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (k8s中)docker netty OOM问题记录
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (函数)颠倒字符串顺序(C语言)
  • (论文阅读11/100)Fast R-CNN
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • .a文件和.so文件
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .net 简单实现MD5
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .NET值类型变量“活”在哪?
  • .NET中使用Redis (二)
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • [Angularjs]asp.net mvc+angularjs+web api单页应用之CRUD操作
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [C++][数据结构][跳表]详细讲解