http学习之路
摘要
在请求的页面里有些静态文件(图片,css,js)不是经常变化的,将这些文件存储起来,也是客户端优化用户浏览体验的一个好方法。http缓存作为web性能优化的重要手段,但是对于前端来说只是知道浏览器会对静态文件进行缓存,但为什么被缓存,缓存是怎么失效的并不清楚。下面为大家介绍http的缓存机制。
http缓存分类
缓存分为强制缓存和协商缓存,强制缓存在缓存数据未失效情况下,不需要和服务器进行交互。而协商缓存需要进行和服务器进行比较和判断是否进行缓存。
两种缓存同时存在的情况下,强制缓存优先于协商缓存。
强制缓存
1. Expires
expires的值是告诉浏览器的缓存过期时间(值为GMT时间,即格林尼治时间),即下次请求时,没有到达过期时间,浏览器会直接使用缓存数据。
虽然这种方式添加了缓存控制,节省了流量,但还是存在很多问题
(1) 由于客户端时间是服务器没办法控制的时间,假如用户改变了客户端时间,就可能造成一些缓存的更新不及时
(2) 缓存过期后,不管文件有咩有发生变化,浏览器都会重新请求服务器
2. Catch-Control
针对以上浏览器和服务器时间不一致问题,加入了新的缓存方案,服务器不直接告诉浏览器过期时间,而是告诉浏览器一个相对时间Cache-Control=10秒,意思是10秒内,直接使用浏览器缓存。
协商缓存
强制缓存的弊端很明显,都是通过时间判断是否请求服务器加载,但是如果文件没有发生变化,就会造成浪费服务器的资源。
协商缓存有两组报文结合使用
Last-modified
为了节省服务器资源,再次改变方案。浏览器和服务器协商,服务器每次返回文件时,都会告诉浏览器文件在服务器上最近修改的时间,请求的过程如下:
- 浏览器请求静态资源Demo.png
- 服务器读取磁盘,返回给浏览器文件,并带上文件上次修改时间Last-Modified(GMT标准格式)
- 当浏览器缓存文件过期时,浏览器会带上If-Modified-since(等于上次请求的last-modified)请求服务器。
- 服务器比较请求头里的If-modified-since和文件上次修改的时间,如果文件一致就继续使用浏览器的缓存(304),不一致就重新请求服务器并返回last-modified
- 循环请求。。。。
虽然这个方式比上面三个方式都有进一步的优化,浏览器检测文件是否有变化,如果没有变化,就直接使用缓存文件还是有些问题:
- last-modified是使用(GMT)时间,只能精确到秒,如果文件在一秒之内改变很多次,浏览器就没办法去识别并请求新的文件。
- 如果文件经过多次修改,但是内容没有变化,服务器需要重新返回请求文件。
Etag
为了解决文件修改时间不精确的问题,浏览器再和服务器进行协商,这次不返回时间,返回文件唯一标识Etag,只有当文件内容改变时,Etag才会改变。请求过程如下:
- 浏览器请求静态资源demo.png
- 服务器读取磁盘,把demo.png文件返回给浏览器,并带上文件的唯一标识Etag
- 当浏览器的缓存文件过期时,浏览器带上If-None-Match(等于上次上次的Etag)再次请求服务器
- 服务器比较请求头的If-None_Match和文件的Etag,如果一致就继续使用缓存文件(304),不一致带上Etag重新请求服务器。
- 循环请求。。。
关于Pragma
当该字段值为no-cache的时候,会告诉浏览器不要对该资源缓存,即每次都得向服务器发一次请求才行。
res.setHeader('Pragma', 'no-cache') //禁止缓存
res.setHeader('Cache-Control', 'public,max-age=120') //2分钟复制代码
通过Pragma来禁止缓存,通过Cache-Control设置两分钟缓存,但是重新访问我们会发现浏览器会再次发起一次请求,说明了Pragma的优先级高于Cache-Control
关于Cache-Control
我们看到Cache-Control中有一个属性是public,那么这代表了什么意思呢?其实Cache-Control不光有max-age,它常见的取值private、public、no-cache、max-age,no-store,默认值为private,各个取值的含义如下:
- private: 客户端可以缓存
- public: 客户端和代理服务器都可缓存
- max-age=xxx: 缓存的内容将在 xxx 秒后失效
- no-cache: 需要使用对比缓存来验证缓存数据
- no-store: 所有内容都不会缓存,强制缓存,对比缓存都不会触发
所以我们在刷新页面的时候,如果只按F5只是单纯的发送请求,按Ctrl+F5会发现请求头上多了两个字段Pragma: no-cache和Cache-Control: no-cache。
缓存的优先级
上面我们说过强制缓存的优先级高于协商缓存,Pragma的优先级高于Cache-Control,那么其他缓存的优先级顺序怎么样呢?网上查阅了资料得出以下顺序(PS:有兴趣的童鞋可以验证一下正确性告诉我):
Pragma > Cache-Control > Expires > ETag > Last-Modified