Web 缓存大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存。其中前端比较关心的是浏览器缓存,包括今天要说的HTTP缓存和前面说过的cookie、localStorage等存储。(资源缓存仅针对get请求,post、put、delete等行为性操作无缓存)。

HTTP缓存分为强缓存和协商缓存。通过特殊的HTTP中的cache-control首部和expries首部,说明文档是否过期,浏览器二次请求相同资源时,进行比较,没有过期则为强缓存。过期则核对是否修改,但是缓存过期仅代表需要进行核对,而不一定是资源有了差异,客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存,这便是协商缓存。

from-cache:

  • 200:缓存命中
  • 304:再匹配未修改(not modified)

强缓存

Cache-Control和Expires

强缓存利用Expires和Cache-Control两个字段来控制。expires:是缓存过期时间(即资源过期时间),是个绝对值。所以如果客户端更改时间,会导致缓存混乱。所以http1.1增加了cache-control,由多个字段组合而成,其中max-age 字段,它是一个相对的时间。

  • Cache-Control是HTTP1.1中新增的响应头,Expires是HTTP1.0中的响应头
  • Expires指定的是具体的过期日期而不是秒数,Cache-Control使用的是相对时间
  • Cache-Control和Expires同时使用的话,Cache-Control会覆盖Expires

Cache-Contro相关属性

max-age(单位为s)

指定设置缓存最大的有效时间,当浏览器向服务器发送请求后,在max-age这段时间里浏览器就不会再向服务器发送请求了。

public

指定响应可以在代理缓存中被缓存,于是可以被多用户共享。如果没有明确指定private,则默认为public。

private

响应只能在私有缓存中被缓存,不能放在代理缓存上。对一些用户信息敏感的资源,通常需要设置为private。

no-cache

表示必须先与服务器确认资源是否被更改过(依靠If-None-Match和Etag),然后再决定是否使用本地缓存。

no-store

绝对禁止缓存任何资源,也就是说每次用户请求资源时,都会向服务器发送一个请求,每次都会下载完整的资源。通常用于机密性资源。

协商缓存

浏览器或代理缓存中缓存的资源过期了,并不意味着它和原始服务器上的资源有实际的差异,仅仅意味着到了要进行核对的时间了。这种情况被称为服务器再验证,也就是协商缓存:

  • 如果资源发生变化,则需要取得新的资源,并在缓存中替换旧资源。
  • 如果资源没有发生变化,缓存只需要获取新的响应头,和一个新的过期时间,对缓存中的资源过期时间进行更新即可。

HTTP1.1推荐使用的验证方式是If-None-Match/Etag,在HTTP1.0中则使用If-Modified-Since/Last-Modified。

If-None-Match/Etag

Etag是指根据实体内容生成一段hash字符串,标识资源的状态,由服务端产生,第一次请求响应头会带上ETag: abcd,之后的请求中带上 If-None-Match: abcd。浏览器会将这串字符串传回服务器,验证资源是否已经修改,返回 304 或 200。

If-Modified-Since与Last-Modified

Last-modified: 服务器端资源的最后修改时间,响应头部会带上这个标识。第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since 即为之前记录下的时间。服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304。这两个是HTTP1.0中用来验证资源是否过期的请求/响应头,这两个头部都是日期,验证过程与Etag类似,这里不详细介绍。使用这两个头部来验证资源是否更新时,存在以下问题:

  • 有些文档资源周期性的被重写,但实际内容没有改变。此时文件元数据中会显示文件最近的修改日期与If-Modified-Since不相同,导致不必要的响应。
  • 有些文档资源被修改了,但修改内容并不重要,不需要所有的缓存都更新(比如代码注释)

如果响应头中有 Last-modified 而没有 Expire 或 Cache-Control 时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以 Last-modified 要记得配合 Expires/Cache-Control 使用。

last-modified 和 Etag 区别

  • 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。
  • Last-modified 只能精确到秒。
  • 一些资源的最后修改时间改变了,但是内容没改变,使用 Last-modified 看不出内容没有改变。
  • Etag 的精度比 Last-modified 高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供 ETag 的话,必须先对 ETag 进行 Conditional Request。

应用

使用缓存的原因:

  • 冗余的数据传输
  • 带宽瓶颈
  • 瞬间拥塞
  • 距离时延

缓存场景:

  • CSS文件、js文件、html文件
  • 图标、图片
  • 供下载的附件

缓存时间:

  • 不经常改变的文件,设置较大的max-age,一般设置max-age=31536000(标准中规定 max-age 的值最大不超过一年,所以设成 max-age=31536000)
  • 经常需要变动的文件,Cache-Control: no-cache / max-age=0

前端HTTP缓存的更多相关文章

  1. 前端清除缓存方法(微信缓存引起的bug)

    bug1:在新版微信中,部门安卓机子(华为)出现window.location.href/window.location.reload....等方法来刷新本页面链接,发现页面没有被刷新,经过排查,发现 ...

  2. 深入浅出的webpack4构建工具---浏览器前端资源缓存(十一)

    阅读目录 一. 理解使用hash 二:理解使用chunkhash 三:对第三方库打包后使用缓存 四:contenthash 回到顶部 一. 理解使用hash 一般情况下,对于前端静态资源,浏览器访问的 ...

  3. Web前端的缓存机制(那些以代价换来的效率)

    对于Web前端而言,cache可以说是无处不在,通常是2个环节之间,就会引入一个cache做为提升整体效率的角色.例如A和B两者之间的数据交换,为了提升整体的效率,引入角色C,而C被用于当做热点数据的 ...

  4. HTML5之应用缓存---manifest---缓存使用----Web前端manifest缓存

    相信来查这一类问题的都是遇到问题或者是初学者吧! 没关系相信你认真看过之后就会知道明白的 这是HTML5新加的特性 HTML5 引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连 ...

  5. 前端内容缓存技术:CSI,SSI,ESI

    一.CSI (Client Side Includes)   含义:通过iframe.javascript.ajax  等方式将另外一个页面的内容动态包含进来. 原理:整个页面依然可以静态化为html ...

  6. 缓存:前端页面缓存、服务器缓存(依赖SQL)MVC3

    缓存依赖数据库 第一步 1通过vs里面带的命令提示窗口. 2或者.NET Framework 版本 4(64 位系统)条件,%windir%\Microsoft.NET\Framework64\v4. ...

  7. 前端图片缓存之通过img标签加载GIF只能播放一次问题(转载)

    最近项目中要求再网页中插入一张gif图片,让用户每次到达该位置时动一次,所以我们就制作了一张只动一次的gif图片通过img标签引入.当用户进入该位置时,通过remove()清除图片然后重新append ...

  8. 前端不缓存,ajax不缓存,js操作cookie

    今天实现网站注销功能时,需要清除cookie缓存,开始在网上搜索的是“js清除缓存”,发现很多都是预先防患缓存存储的内容,千篇一律,不过也学习到了:后来换成"js清除cookie" ...

  9. 【移动前端开发实践】从无到有(统计、请求、MVC、模块化)H5开发须知

    前言 不知不觉来百度已有半年之久,这半年是996的半年,是孤军奋战的半年,是跌跌撞撞的半年,一个字:真的是累死人啦! 我所进入的团队相当于公司内部创业团队,人员基本全部是新招的,最初开发时连数据库都没 ...

随机推荐

  1. 应用安全 - 软件漏洞 - 可视化平台kibana漏洞汇总

    CVE-2019-7609  Date: 类型: RCE 前置条件: Timelion And Canvas 影响范围: kibana-RCE < PoC | ExP: https://gith ...

  2. 使用logstash收集java、nginx、系统等常见日志

    目录 1.使用codec的multiline插件收集java日志... 1 2.收集nginx日志... 2 3.收集系统syslog日志... 3 4.使用fliter的grok模块收集mysql日 ...

  3. docker--docker 容器操作

    6 docker 容器操作 容器是 docker 镜像的运行时实例. 6.1 创建容器 docker run [options] image command [ARG...]options选项: ‐i ...

  4. 安装CentOS7虚拟机

    基础环境 Windows 10 VMware Workstation 1.下载CentOS7镜像 https://www.centos.org/download/ 此次安装使用的版本为: CentOS ...

  5. 图——图的Prim法最小生成树实现

    1,运营商的挑战: 1,在下图标出的城市间架设一条通信线路: 2,要求: 1,任意两个城市间都能够通信: 2,将架设成本降至最低: 2,问题抽象: 1,如何在图中选择 n - 1 条边使得 n 个顶点 ...

  6. python day1-requests

    一.什么是requests Requests是用python语言基于urllib编写的,采用的是Apache2 Licensed开源协议的HTTP库. 相对于urllib库(自带,无需手动安装)而言, ...

  7. 在Myeclipse下查看Java字节码指令信息

         在实际项目开发中,有时为了了解Java编译器内部的一些工作,需要查看Java文件对应的具体的字节码指令集,这里提供两种方式供参考. 一.使用javap命令      javap是JDK提供的 ...

  8. XIB约束布局问题(button)

    button默认不给宽度:系统Xib自动适配,最小宽度30.在使用宽度计算时,无法小于这个值

  9. background的水平条纹和斜向条纹

    水平条纹: <div id="div1"> </div> linear-gradient属性 #div1{ width: 100px; height: 10 ...

  10. mirror - 映射在远端节点上的档案

    总览 SYNOPSIS mirror [flags] -gsite:pathname mirror [flags] [package-files] 描述 DESCRIPTION Mirror 是以 P ...