五分钟了解前端缓存机制

前言

任职一年多,经常有测试问我:哎呀,测试环境没看见更新啊。我通常会回复清缓存刷新页面就好了。至于缓存机制,因涉及到前后端,也没去深究。

但是客户不会每次清缓存再访问公司的网站,难道要我们逐个客户打电话过去:麻烦清下缓存,我们更新文件了?理想的情况应该是,我们每次上线版本,客户都能第一时间获取到最新的页面。

因而这次我通过node搭建服务器来搞清前端缓存到底是怎么运作的。

缓存机制

类型

缓存分为两类:强制缓存协商缓存,定义如下:

  • 强制缓存:客户端直接从缓存中读取数据,不与服务器作交互。
  • 协商缓存:客户端发送特定的报文到服务器,服务器根据接收到的报文判断资源是否有更新,有则返回200和最新的资源文件,无则返回304使客户端从缓存中读取数据。

通俗来讲,一个是直接读取浏览器缓存,一个是跟服务器打个招呼:有更新文件嘛?有就给我最新的吧,没有我自己回去读缓存。

缓存由什么决定?

缓存由http报文的内容决定,关系如下:

max-age或者expires都决定了缓存的过期时间,会使客户端再次请求数据时先判断缓存是否过期,未过期则直接从缓存中读取数据(强制缓存);两者的区别是前者是个相对值,相对于客户端的时间,后者直接定义了截止时间,且相对于服务端的时间。

协商缓存由Last-Modified、If-Modified-Since 或 ETag、If-None-Match两组报文决定。字段的意思分别如下:

  • Last-Modified:表示服务器上某文件最近的修改时间,存在于响应报文
  • If-Modified-Since:值等于Last-Modified,存在于请求报文,用于将Last-Modified值返回给服务端作比较。

ETag的If-None-Match的作用类似。

缓存的总体过程

第一次请求资源

再次请求资源

在第一次请求资源后,浏览器会将资源连同响应报文一起缓存到本地,其中响应报文可能包含了关于缓存的头信息。因而后续请求的时候,浏览器可以根据本地缓存的头信息知道资源的缓存决策,判断是否强制缓存,或者移交服务器判断是否协商缓存。

缓存的优先级

如果资源的第一次请求同时返回了max-age和expires,那么判断缓存是否过期时该看哪个?或者同时返回了Etag和Last-Modified,那么服务器协商缓存时由哪个决定?这涉及到缓存的优先级:

  • 强制缓存 > 协商缓存 ---- 从先判断强制缓存,再判断协商缓存可以看出
  • Pragma > Cache-Control: max-age=xxx > Expires
  • Etag > Last-Modified

关于缓存的种种代码

meta标签(无效)

html页面头部可能会加上以下代码来设置缓存

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
复制代码

关于meta标签设置缓存,我实测过程中并没有起到效果,无论是请求头,响应头,或是chrome缓存中保存的信息,都看不到meta设置的信息。

网上查阅过程中发现大部分文章都只是千篇一律地将定义介绍了一遍,后来看到w3cschool对于http-equiv的介绍,如下:

http-equiv可用的值并没有cache-control、pragma,虽然有expires,但是实测也还是没有效果,而另一个网站-菜鸟教程,对于http-equive的介绍中已经去除了expires,如下:

不管怎么样,现在并不能通过设置meta标签来控制缓存了。

客户端控制缓存的方式由不同浏览器的机制决定,下面会有讲解。

文件资源路径加上?v=num后缀

现在项目中,在每次编译压缩前端代码时,都会在js、css的引用路径后加上?v=不同的num来控制缓存。

对于浏览器来说,这是个障眼法,使得浏览器误以为文件不在缓存中,从而发起新的请求。

结合缓存机制来讲,这是一种禁止强制缓存的方式,也就是说浏览器在请求某个资源时,必须与服务器交互,然后服务器决定是直接返回新资源还是协商缓存。

这是个好办法,但前提是必须保证html文件是最新的。

浏览器常用操作等对缓存的影响

chrome下测试

操作影响
F5刷新 或 地址+Enter对于html文件:浏览器在请求头自动加上了cache-control: max-age=0,效果为禁用强制缓存,立即访问服务器,服务器返回最新资源或协商缓存;
对于iframe中的html文件:不自动加上其它参数;
对于其它资源文件:如果有配置max-age,则以配置为主,不会自动加上max-age=0
Ctrl + F5浏览器在请求头自动加上了cache-control: no-cache(相当于max-age=0) 和 pragma: no-cache,并去除协商缓存相关的头信息(If-Modified-Since和If-None-Match),效果为立即访问服务器,且服务器只能返回最新资源
前进、后退不管缓存类型、过期什么的,都是直接使用缓存

firefox下测试

操作影响
地址 + Enter如果有配置max-age,则以配置为主,不会自动加上max-age=0
F5刷新浏览器在请求头自动加上了cache-control: max-age=0,效果为禁用强制缓存,立即访问服务器,服务器返回最新资源或协商缓存;
Ctrl + F5浏览器在请求头自动加上了cache-control: no-cache(相当于max-age=0) 和 pragma: no-cache,并去除协商缓存相关的头信息(If-Modified-Since和If-None-Match),效果为立即访问服务器,且服务器只能返回最新资源
前进、后退不管缓存类型、过期什么的,都是直接使用缓存

所以当测试妹纸问你页面怎么没更新的时候,直接让她Ctrl + F5刷新就ok了。

最好的缓存方式

最好的缓存方式是:

  1. 客户端能够缓存一些较大的资源文件,特别是对于单页应用,可以有效减少页面加载时间;
  2. 当每次服务器更新文件时,客户端都能第一时间获取到最新资源。

个人觉得最好的实现方式是:

  • html页面文件使用“协商缓存”。不使用强制缓存的原因是,无法保证html文件是最新的。
  • 其它资源文件使用“路径后缀 + 无限期强制缓存”。
    1. 平常未更新文件时,强制缓存可以使浏览器直接读取缓存资源,减少与服务器通信的时间。
    2. 更新前端文件后,html中资源文件的路径后缀产生了变化,使得html文件也是修改状态,因html页面没有使用强制缓存,客户端可以获取到最新的html文件,这时浏览器开始解析html文件,其中资源路径后缀变化导致浏览器找不到对应的缓存,从而向服务器请求,这时服务器会直接返回最新的资源。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值