[前端]浏览器缓存问题
- 缓存问题描述
- 为什么需要缓存
- 缓存的优劣
- 优势
- 劣势
- 缓存的使用
- 流览器的三级缓存原理
- 缓存出现的场景
- 缓存的相关概念
- http状态码 & size 说明
- 状态码-304
- 内存 (memory cache)
- 磁盘(disk cache)
- 缓存的存储方案
- Cookie
- Web storage
- IndexDB
- 服务器如何判断是否发生变更
- 交互
- 资源
- 指令
- 指令总览
- 缓存变更的校验
- 缓存指令的优先级
- 页面缓存策略
- 页面指令
- 页面指令的使用方法
- 页面指令应用测试
- 交互的缓存策略
- Cache-Control
- 请求头配置说明
- 请求头配置应用
- 响应配置说明
- 响应配置应用
- 缓存的性能优化策略
- 缓存问题汇总
- 页面缓存--HTML 缓存问题
- 交互的缓存问题
- 目前比较稳妥的方法有添加额外参数时间戳
- nginx 缓存配置
缓存问题描述
在开发过程中会遇到的缓存问题,主要是由两种方式引起的:
- 一种是数据交互请求,用于获取数据;例如,页面通过点击按钮获取最新数据,但是浏览器中(IE浏览器)通过 get 方式获取一次数据之后,再次点击搜索按钮(参数完全相同时)获取到的数据始终是之前的数据,并没有获取到最新的数据(明确数据库数据已经发生变化)
- 一种是资源交互请求,用于获取静态资源;例如,css 文件、js文件、html文件等。遇到的缓存情况是,变更了 css 文件的内容,但是文件名称没有发生变化,导致刷新页面之后页面加载的 css 文件并不是最新的 css 文件
在上述情况中会多次返回 304 状态码,我们知道,在交互中,状态304码表示客户端已经执行 GET,但文件未变化
,所以将使用缓存数据
以上问题都是缓存导致的,那么为什么需要缓存呢,既然会导致数据无法更新等各种问题,为什么还要使用缓存呢?
为什么需要缓存
我们知道一般系统或网页上线之后,如果没有出现更新的情况下,这些静态资源一般是不会发生变化的,那么在每次打开系统的时候重新请求该静态资源就是对网络资源(如是手机网页,就是浪费流量)的浪费,因为之前已经请求过了,所以缓存是很有必要的。
所以就需要一个合适的缓存策略,我们希望数据交互的时候每次都拿到的是最新的数据,不要使用缓存数据;而获取静态资源时,希望当资源发生变更的时获取最新资源,否则使用缓存资源
缓存的优劣
使用缓存有时会导致意想不到的情况发生,就是资源更新后确使用了缓存的未更新的资源,所以我们要避免这种情况的发生
优势
资源访问的时候直接使用客户端(客户端一般情况是浏览器,也可能是桌面版软件)的缓存资源,避免带宽资源的浪费
劣势
若是出现资源的变更,直接使用客户端的缓存资源,会导致不可预测问题
所以希望资源在未发生变更时直接使用缓存资源;若是发生变更希望使用从服务器获取到的变更后资源
缓存的使用
客户端获取资源或数据交互的时候,决定是否使用缓存,是客户端(也即浏览器)判定的
。
但是以上说法也并不准确
,是当资源第一次加载完成后,客户端再次需要该资源的时候,根据资源第一次加载的响应指令和页面指令等设置,决定是否使用使用缓存。
流览器的三级缓存原理
如果客户端需要某个资源:
- 先是从客户端缓存存取位置查找内存
- 如果内存位置没有需要的缓存资源,然后是查找磁盘,
- 若以上位置均没有,就会通过网络查找,也就是去服务端获取资源
缓存出现的场景
资源允许缓存,并且没有资源更新的情况下
,查看网页的几种情况:
-
打开新窗口
第一次打开网页,此时浏览器没有缓存信息,资源都是从服务器获取,然后根据缓存策略缓存资源;
再次打开网页,在谷歌浏览器中所有js/css/image资源都是从Disk Cache中获取 -
地址栏回车
若是第一次访问网页时会访问服务器获取资源;
非第一次访问网页,在该网页打开的情况下回车,也就是刷新网页,因为加载过资源,所以此时内存中是存在该资源的,所以使用资源的情况是从内存中获取;根据浏览器的三级缓存原理,若是页签关闭,内存中资源会被删除,此时新开页签,输入地址回车,因为内存中没有该资源,因此从Disk Cache中加载 -
按浏览器后退按扭
相当于再次访问网页 -
按浏览器刷新按扭
等同于地址栏回车
缓存的相关概念
http状态码 & size 说明
网页浏览器第一次加载的状态码与size信息截图;
上图是一个页面再次加载浏览器信息截图
所以针对状态码与size做一个说明:
状态码/size | 说明 |
---|---|
200/数值大小 | 从服务器下载最新资源,表明之前未加载过该资源,数值是从服务器获取的全部资源大小 |
304/数值大小 | 访问服务器,发现资源没有更新,使用本地资源。数值是与服务器通信报文的大小,并不是资源本身的大小。 |
200/memory cache | 状态码是灰色的,从内存中读取之前已经加载过的资源,不请求服务器,页面关闭时,资源就会被内存释放,再次打开相同页面不会出现此类情况,在同一页面刷新才会出现。一般脚本、字体、图片会存在内存当中 |
200/disk cache | 状态码是灰色的,从磁盘中读取之前已经加载过的资源,不请求服务器,页面关闭不会被释放,这部分资源存在电脑磁盘里,只有用户手动清除浏览器缓存的时候才会释放。一般非脚本会存在磁盘中,如css等 |
状态码-304
状态码 304 ,百度百科上解释说如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个 304 状态码。304状态码简单的来说就是服务端的资源未发生变化
客户端是怎么知道这些内容没有更新的呢?其实这不是客户端的事情,而是服务器的事情,服务器可以设置缓存机制,这个功能是为了提高网站的访问速度,当客户端发出 GET 请求的时候,服务器(网页服务器,或者数据交互的服务器)会从缓存中调用你要访问的内容,这个时候服务器就可以判断这个页面是不是更新过了,如果未更新过那么他会给你返回一个 304 状态码。
内存 (memory cache)
资源存储在内存中
,当页面关闭时,资源会被内存释放,再次打开该页面资源会重新请求,因为之前被释放掉了;当页面直接刷新时,因为资源没有被释放,所以会从浏览器缓存中获取
内存资源获取速度快,优先级高,但是生命周期短,但是网页关闭后内存会被释放,并且内存大小受限于计算机内存大小,如果存储资源过大仍旧会使用硬盘(磁盘)
磁盘(disk cache)
资源存储在磁盘中
,如果没有特意清理,资源将始终保存在磁盘上,所以当页面关闭时,资源不会被释放。一般磁盘就是我们所谓的计算机硬盘
硬盘的优点是生命周期长,不触发删除操作,资源不会被删除,缺点是资源获取速度相对内存而言比较缓慢
资源从内存中获取比从磁盘中获取会更快,在内存中获取资源几乎不耗时
缓存的存储方案
可以通过 Cookie 、 Web storage 、IndexDB 存储
Cookie
Cookie 的存储空间很小,不能超过 4KB,不建议将非用户身份类的数据存储在 Cookie 中,因为 Cookie 随着同域名下每一次资源请求的请求报头传递到服务端进行验证,如果大量非必要的数据存储在 Cookie 中,伴随着请求响应会造成无效资源传输及性能浪费
并且浏览器提供的cookie存储与读取API并不是很好使用
document.cookie='odeon_username=username; domain=cookie.iflytek.com'
// 设置cookie过期时间
let date = new Date()
date.setTime(date.getTime() - 10000)
document.cookie=`odeon_username=username; domain=cookie.iflytek.com; expires=${date.toGMTString()}`
Web storage
在验证用户身份及维持状态方面,Cookie 有明显的特点和优势,但是数据存储方面并不适合使用cookie
Web storage是H5推出的存储方案,包括 Session Storage 和 Local Storage,存储空间一般为 2.5-10M 之间(不同浏览器存储空间不同)。
Session Storage是临时性存储,是网页会话期间存在,网页关闭后释放。
Local Storage是持久性存储,存储在浏览器本地,除非过期或手动删除,否则一直存在
IndexDB
IndexedDB 是一个大规模的 NoSQL 存储系统,几乎可以存储浏览器中的任何数据内容,包括二进制数据(ArrayBuffer 对象和 Blob 对象),其存储空间一般不少于 250M 的数据。
在使用 IndexedDB 前,需要判断浏览器是否支持:
if (!('indexedDB' in window)) {
console.log('浏览器不支持 IndexedDB')
return
}
在浏览器支持的前提下,便可以对其进行增删改查操作。
- 首先我们先得打开或者创建数据库:
let idb
// 打开名为 dbTest ,版本号为 1 的数据库,如果不存在则自动创建
let request = window.indexedDB.open('dbTest', 1)
// 错误回调
request.onerror = function (event) {
console.log('打开数据库失败')
}
// 成功回调
request.onsuccess = function (event) {
idb = request.result
console.log('打开数据库成功')
}
具体的增删改查就不在这里赘述了,感兴趣的可以自己查阅
服务器如何判断是否发生变更
交互
如果是数据交互的话,我们可以在请求头设置缓存规则;同一个请求根据参数,也即搜索条件有没有发生变化,此时是浏览器策略会先判断是否发生变更,若是参数没有变化,可能直接使用缓存数据,都不去服务去获取新的数据,那么为了避免相同搜索条件使用缓存数据,被浏览器直接拦截,为每次请求添加时间戳参数,或者随机数参数,表示新的请求,去服务器获取数据
资源
一般资源的获取,若是同名的静态资源内部发生了更新的情况,此时根据文件名根本无法判断当前资源已经更新了!!!所以需要其它标志判断,此文件已经更新。目前知道的标志包括Last-Modified
,若是Last-Modified
相同就会返回状态码 304;
但是存在根据浏览器返回的内容显示返回的不是状态码 304,而是 200的场景!!这说明在完全不设置的情况,也就是默认情况应该是返回304,但是当设置了缓存策略后,是否仍从缓存获取资源就要看配置了
指令
指令总览
发现很多指令,既可以在页面中设置,也可以在nginx 中配置,所以对所有的与缓存可能相关的指令做一个说明:
- Cache-Control
- 是 http1.1 的指令,只能应用于 http 1.1
- 一般该标志出现在请求头中
- 用于告诉客户端(浏览器)请求或者响应的缓存机制
- 可以用来设置页面被缓存最大时限,缓存的方式,如何被转换到另一个不同的媒介,以及如何被存放在持久媒介中的。
- 取值包括:
- max-age
- 用来设置缓存时间,表明资源被缓存最大时限,时限内刷新网页使用缓存,超过时间的缓存资源不可用
- max-age=0,表示不缓存
- max-age=5,表示5秒内需要该资源使用缓存资源,超过5秒需要去服务器重新获取
- no-cache
- 也叫协商缓存,是在使用缓存资源之前需要和服务器
确认
该资源没有发生变更!!!! - 需要通过标识判断是否发生变更,如果匹配,则使用缓存资源;如果匹配不上,发现资源发生变更,将会获取新的资源
- 一般通过 Last-Modified/IF-Modified-Since、Etag/IF-None-Match 标识确认资源是否发生变更。一般先对比Etag,如果一致,再对比Last-Modified
- 也叫协商缓存,是在使用缓存资源之前需要和服务器
- must-revalidate
- 必须重新验证,是指当设置
max-age=number
,资源过期之后,使其重新生效必须到服务器验证过才可以生效(存在直接使过期缓存生效的场景)
- 必须重新验证,是指当设置
- no-store
- 资源不会被缓存,不论什么情况都不使用缓存
- private
- 资源客户端可以缓存
- 默认Cache-Control取值为 private
- public
- 资源客户端和服务器都可以缓存
- s-maxage
- 表明资源被服务器缓存最大时限
- 必须和 public 属性一起使用
- max-age
- 该指令不能保证数据的隐私性或者安全性。但是其中private和no-store指令可以为隐私性和安全性方面提供一些帮助,但是他们并不能用于替代身份验证和加密。
- Last-Modified
- 一般该标志出现在响应头中,表示资源在服务器最后修改时间
- Last-Modified 和 ETag 是条件请求(Conditional Request)相关的两个字段。
- 如果一个缓存收到了针对一个页面的请求,它发送一个验证请求询问服务器页面是否已经更改,在 HTTP 头里面带上 “ETag” 和"If Modify Since"头。服务器根据这些信息判断是否有更新信息,如果没有,就返回 HTTP 304(NotModify);如果有更新,返回 HTTP 200 和更新的页面内容,并且携带新的"ETag" 和"LastModified"。
- 使用这个机制,能够避免重复发送文件给浏览器,不过仍然会产生一个 HTTP 请求。
- ETag
- 是 http1.1 的指令
- 一般该标志出现在响应头中,是资源文件的唯一标识符
- 既然有了 Last-Modified,为什么还要用 ETag 字段呢?因为如果在一秒钟之内对一个文件进行两次更改,Last-Modified 就会不正确。因此,Entity Tag 头提供了更加严格的验证
- If Modify Since
- 一般该标志出现在请求头中,是上次响应头中的Last-Modified
- 表明请求资源的上次的修改时间,可以和服务器中的作比较
- 判断是否使用缓存的条件之一
- If-None-Match
- 一般该标志出现在请求头中,是上次响应头中的ETag
- 表明请求资源的ETag标志,可以在服务器中查找是否有匹配资源
- 判断是否使用缓存的条件之一
- Expires
- 是 http1.0 的指令
- 网页或 URL 地址不再被浏览器缓存的时间
- 设置过去的时间,则不会缓存,每次都去服务器重新获取,例如,Fri, 31 Dec 1999 16:00:00 GMT
- 如果服务器上的网页经常变化,就把它设置为 0,表示立即过期
- 禁止页面在 IE(浏览器) 中缓存,可以 设置http 响应头:
CacheControl = no-cache Pragma=no-cache Expires = -1
.
- Pragma
- 是 http1.0 的指令,可以应用到 http 1.0 和 http 1.1
- 禁用网页缓存的指令,浏览器也就不支持脱机浏览
- 取值:no-cache
- 作用类似于Cache-Control,主要是为了兼容http 1.0
缓存变更的校验
HTTP 条件方法可以实现高效的再验证,向服务发送 “条件 GET” 目前最常用的为 If-Modified-Since
:Date, If-None-Match
:ETag(实体标签,版本标识)
If-Modified-Since
表示在指定日期之后资源被更新,就返回新的请求,如果指定日期未更新就返回 304 直接读取缓存
If-None-Match
有的文档有可能周期性的被重写,通过 ETag 来确保文档是否改变,改变,返回请求状态为 200 的新资源;未改变,返回状态码 304 直接读取缓存
这些可以结合使用。
缓存的内容不一定每次都与服务器来进行验证,不同的浏览器对于请求中 Cache-Control 的值和响应中 Cache-Control 的值的优先级是不一样的。
缓存指令的优先级
缓存指令挺多的,如果出现冲突的时候,优先级就很重要:
Cache-Control > max-age > Expires
页面缓存策略
页面指令
以上指令中可以直接用于html页面的指令包括:
- Expires
- Cache-Control
- Last-Modified
- ETag
页面指令的使用方法
指令在页面中的应用:
<meta http-equiv="Cache-Control" content="no-store" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
根据以上代码,http-equiv 描述要设置的指令,content 表示要设置的指令值;
页面指令应用测试
以下资源都是被index.html中被引入的资源:
- 同一个图片,内容变更,但是打包后文件名未变。例如, vue 项目下 public 文件夹中 favicon.ico 图片变更
-
刷新后结果
IE:未更新/ Firefox:未更新/ Chrome:更新 -
解决方案
发生变更后修改 href 添加一个随机数,刷新则随机数不同,即可重新获取图片,不从缓存中获取
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico?<%= Math.random()%>">
- css 文件内容变更,打包后在 index.html 引入的文件名变更
-
刷新后结果
IE:更新/Firefox:更新/Chrom:更新
-
解析
js/css 文件更新后浏览器获取到的都是最新的文件,原因是当样式或逻辑变更后打包生成的 js/css 文件的 hash 值也发生变更,因此不存在获取缓存文件的问题,如果是在 html 中直接添加的文件引入,发生变更的情况,也可以添加随机数处理
此种场景需要注意的是刷新后加载的index.html不是缓存文件,否则获取到的 index.html 文件就不是含有变更后hash值名字的 js/css 文件
html 中通过 meta 添加的设置只是限制加载的 html 本页不缓存,html页面本身每次都重新获取,但是 html 页面中发出的请求,不论是静态资源还是数据交互请求,是无法通过meta设置的 no-cache/no-store 控制,并且经过测试,两种值都对页面中的请求没有起作用,IE 一样缓存,该设置只对当前页存在影响,例如:html 发生变化时
-
IE 截图
浏览器返回的内容显示返回的不是状态码 304,而是 200,但是可以看到显示的提示"来自缓存"
-
Chrome 截图
交互的缓存策略
Cache-Control
Cache-Control 指定请求和响应遵循的缓存机制;设置在请求头或者响应头中
对于 cache-control 的应用有三种,其作用根据重新浏览方式的不同分为以下几种情况:
在请求消息或响应消息中设置 Cache-Control 并不会影响另一个消息处理过程中的缓存处理过程;
请求时的缓存指令值: no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached;
响应时的缓存指令值: no-cache、no-store、max-age、 no-transform、must-revalidate、proxy-revalidate、 public 、 private
各个交互中的指令取值含义如下:
指令 | 说明 |
---|---|
no-cache | 设置请求或响应消息不缓存 |
no-store | 防止重要信息被发布。在请求消息中发送将使请求和响应消息都不使用缓存 |
max-age | 客户端可接收生存期不大于指定时间(以秒为单位)的响应 |
min-fresh | 客户端可接收响应时间小于当前时间+指定时间的响应 |
max-stale | 客户端可接收超出超时期间的响应。如果有值则接收超时后该值的响应消息 |
public | 响应可被任何缓存区缓存 |
private | 对于用户响应消息的缓存不能被共享。此响应消息对其他用户请求无效 |
请求头配置说明
指令 | 说明 |
---|---|
no-cache | 除非资源进行了再验证,否则客户端不会接受已经缓存的资源 |
no-store | 缓存尽快从存储器中删除资源痕迹 |
max-age=s | 缓存不返回缓存时间>s 秒的文件,定义 max-age 后,缓存内容不一定每次都需要服务器验证,但是过期后一定会向服务器验证,该指令使缓存更加严格 |
max-stale=s | 缓存可随意提供过期文件,如果指定了参数s 在这段时间内,文档不过期 |
min-fresh | 当缓存中有副本文件存在,客户端才会获取副本 |
only-if-cached | 当缓存中有副本文件存在,客户端才会获取副本 |
请求头配置应用
请求头一般是前端开发中配置的,属于客户端
headers: {
//当只设置cache-control: 'no-cache'时
//IE浏览器始终返回304,抓包工具抓不到包,请求不和服务器确认
//google浏览器始终返回200,抓包工具可以抓取包,请求重新从服务器获取数据,没有利用到浏览器的缓存功能
'cache-control': 'no-cache',
//当只设置Pragma: 'no-cache'时,禁用缓存
//IE浏览器始终返回200,抓包工具可以抓到所有包,请求重新从服务器获取数据,没有利用到浏览器的缓存功能
//google浏览器始终返回200,抓包工具可以抓到所有包,请求重新从服务器获取数据,没有利用到浏览器的缓存功能
'Pragma': 'no-cache'
//两个参数同时不设置时
//IE浏览器始终返回304,抓包工具抓不到包,请求不和服务器确认
//google浏览器首次返回200,之后始终返回304,并且有和服务器确认
//两个参数同时设置时
//IE浏览器始终返回200,抓包工具可以抓到所有包,请求重新从服务器获取数据,没有利用到浏览器的缓存功能
//google浏览器始终返回200,抓包工具可以抓到所有包,请求重新从服务器获取数据,没有利用到浏览器的缓存功能
}
// 请求拦截器:在发送请求前拦截,可设置请求头
axios.interceptors.request.use(
config => {
// config.headers["cache-control"] = 'no-cache';
config.headers["Pragma"] = 'no-cache';
return config
},
error => {
return Promise.reject(error)
}
);
测试发现仅仅设置 Pragma,在参数相同的条件下,浏览器的交互都会取最新的数据,而不是获取浏览器的缓存;
测试若仅仅设置 cache-control,在参数相同的条件下,浏览器的交互是获取浏览器的缓存,无法获取最新数据;
不确定以上是否受到服务端的影响,导致无法获取最新数据,但是可以肯定 Pragma 可以获取最新数据
响应配置说明
指令 | 说明 |
---|---|
no-cache | 必须先与代理服务器确认是否更改,然后在在决定使用缓存还是请求 |
no-store | 所有内容都不会被缓存 |
max-age=s | 缓存内容在 s 秒后失效,仅 HTTP1.1 可用,定义了 max-age 之后,缓存的内容不一定每次都需要服务器验证,但是在过期后一定需要服务器验证 |
must-revalidation/proxy-revalidation | 如果缓存内容失效,请求必须发送服务器/代理进行验证 |
public | 所有内容都被缓存 |
private | 仅客户端缓存代理服务器不缓存 |
响应配置应用
HttpServletResponse resp = (HttpServletResponse) servletResponse;
resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Credentials", "true");
resp.setHeader("Access-Control-Allow-Methods","POST, GET, HEAD,PUT,OPTIONS, DELETE,PATCH");
resp.setHeader("Access-Control-Max-Age", "1800");
resp.setHeader("Access-Control-Allow-Headers","Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
这个是服务端的设置,未测试,暂时未知
如果服务器在响应中设置了 no-cache 即 Cache-Control:no-cache,那么浏览器在使用缓存的资源之前,必须先与服务器确认返回的响应是否被更改,如果资源未被更改,可以避免下载。这个验证之前的响应是否被修改,就是通过上面介绍的请求头 If-None-match 和响应头 ETag 来实现的。
需要注意的是,no-cache 这个名字有一点误导。设置了 no-cache 之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。如果设置了 no-cache,而 ETag 的实现没有反应出资源的变化,那就会导致浏览器的缓存数据一直得不到更新的情况。
缓存的性能优化策略
Web缓存性能优化是一种提高网站加载速度和提高用户体验的方法。通过使用缓存,可以减少服务器的负载和网络延迟,从而提高页面的响应速度。以下是一些关于Web缓存性能优化的建议:
- 频繁变动的资源,比如HTML,采用协商缓存
- CSS、JS、图片等资源采用强缓存,避开启发式缓存,使用 hash 命名
- 缓存API响应,在相同请求再次发生时,可以直接从缓存中获取结果,而无需重新查询API
- 采用效率更高的br压缩算法,可以减小传输文件的大小,从而缩短加载时间
- 合并请求,把多个访问小文件的请求合并成一个大的请求,虽然传输的总资源还是一样,但是减少请求,意味着减少了重复发送的 HTTP 头部
- 延迟加载,对于不需要立即显示的资源(如图片或视频),可以使用延迟加载技术。这样,只有当用户滚动到这些资源时,它们才会开始加载
- 使用 preload和prefetch优化浏览器资源加载的顺序和时机
- 使用base64,命中 memory cache
- 使用 HTTP2.0,HTTP2.0 协议提供了性能改进,如多路复用和服务器推送。启用HTTP2.0 可以进一步提高网站性能
强缓存,只要缓存资源不过期就使用缓存资源,一般通过 Expires、Cache-Control 设置缓存时间;
协商缓存,使用缓存资源前,要去服务器校验该资源是否发生变更,变更请求新资源,没有变更使用缓存资源;
启发式缓存,是指没有设置过期时间的情况下(没有响应头 Expires、Cache-Control ),但是浏览器希望尽可能的缓存资源,浏览器设置 space=当前时间减去资源的最后修改时间
,与0比较取较大值(一般肯定是space > 0),此时浏览器将 space 的十分之一设置为资源的过期时间,也就是资源的过期时间=Max[0,space]*0.1
,我们将此种情况称之为启发式缓存
缓存问题汇总
页面缓存–HTML 缓存问题
Vue项目,当项目文件发生变化后,打包生成的文件对应的资源文件的hash值都将发生变化,因此不会存在css或者js的缓存问题,唯一有可能引发的问题是index.html文件,因为入口文件始终是index.html,并且打包后名称不会变更!!!!所以若是index.html文件内容发生变更,很可能导致加载的是缓存文件
例如,微服务中项目加载的微服务,在微服务更新后,点击菜单从新打开页面的时候,总是出现页面未更新的情况,此时需要保证index.html文件不缓存,或者是协商缓存(发生变更就要去服务器重新获取)
通过 http-equiv 页面指令设置缓存方式,测试可行
交互的缓存问题
目前比较稳妥的方法有添加额外参数时间戳
添加时间戳的方式,导致参数不同,每个请求都会到服务器去请求
nginx 缓存配置
网上有介绍可以通过nginx配置设置缓存
location ~ .*\.(html)$ { // 对html文件限制缓存
# add_header Cache-Control no-store; 不缓存
add_header Cache-Control no-cache;//替代上面,协商缓存
add_header Pragma no-cache;
}
添加以上代码,希望配置 index.html 的缓存方式,但是该方式连部署都失败了,原因还不明白!!