前端浏览器缓存机制
写作背景
当测试环境前端资源有更新的时候,我们想要测试刚刚部署上去的新功能,或者打的热补丁的效果,却发现前端文件被浏览器缓存了下来,加载的还是上一个版本的文件。
什么是浏览器缓存
Web浏览器在访问网页时会将某些资源(例如HTML、CSS、JavaScript、图像等)保存在本地存储器中,以便在将来的访问中可浏览器缓存以更快地加载和显示页面。
浏览器缓存的基本工作原理
当浏览器首次请求一个网页时,它会将服务器返回的资源保存在本地缓存中,并在后续的请求中使用缓存的资源,而不是再次从服务器下载相同的资源。
当用户再次访问同一网页时,浏览器会首先检查本地缓存,如果资源没有过期或被修改,浏览器将直接从缓存中加载资源。
如何判断资源有没有过期或被修改
- HTTP协议的缓存机制
- 文件指纹
- 缓存清除
HTTP协议的缓存机制
HTTP缓存可以分为
- 强缓存: 浏览器会直接从本地缓存中加载资源,而不会向服务器发送请求
- 协商缓存:通过在浏览器请求资源时,与服务器进行一系列的交互,以确定是否需要重新传输资源
强缓存
通过响应头携带字段来确定,http1.0阶段是通过Expires字段,后来的http1.1中使用Cache-Control字段
Expries:如果浏览器再次请求该资源,并且当前时间早于或等于过期时间,浏览器将直接从缓存中加载该资源,而不发送请求给服务器。
iniExpries: Thu, 01 Dec 1994 16:00:00 GMT => 资源的过期时间是1994年12月1日下午4点(格林尼治标准时间)
Cache-Control

markdown
"no-store":该指令指示浏览器不应该将任何响应内容存储在缓存中。每次请求该资源时,都需要向服务器发送请求并获取完整的响应。这样可以确保每次都获取到最新的资源,适用于对安全性要求较高、敏感数据或私密信息的资源。
"no-cache":该指令要求浏览器在使用缓存之前先向服务器发送请求进行验证。浏览器会向服务器发送一个条件请求,服务器会检查资源是否发生了变化。如果资源未发生变化,则服务器返回状态码304(Not Modified),浏览器使用缓存的资源。如果资源发生了变化,服务器会返回新的资源。这样可以确保浏览器使用的是最新的资源。
"must-revalidate":该指令要求浏览器在使用缓存之前,必须先向服务器发送请求进行验证。类似于"no-cache",浏览器会发送条件请求,服务器进行资源验证。如果资源仍然有效(未发生变化),服务器返回状态码304,浏览器使用缓存的资源。如果资源过期或发生了变化,服务器会返回新的资源。与"no-cache"不同的是,"must-revalidate"指令强制浏览器进行验证,而不是根据缓存的过期时间来决定是否发送请求。
- 两者同时存在,Cache-Control优先级高于Expires
协商缓存
由HTTP协议的缓存机制中的"Cache-Control"和"ETag"、"Last-Modified"等响应头字段进行控制和实现的
协商缓存通过比较资源的特定标识符(如ETag)或最后修改时间(Last-Modified)来判断资源是否需要重新传输,而不是每次都传输整个资源。这减少了数据传输量和网络延迟,提高了性能和效率。
ETag: 根据文件的具体内容生成哈希值,能够具体追踪到资源内容细粒度级别的变化。
Last-modified: 通过时间点来感知,如果在单位时间内修改多次,此时就不能体现修改。
同一个接口,第一次请求的时候,服务器在响应头里面设置ETag和Last-Modified,当下次发送相同的请求时,在请求头If-Modified-Since 和 If-None-Match中带上之前Last-Modified和ETag的值。
服务器拿到这2个值结合自身的实际情况判断,如果还是没有变更则告诉浏览器(code 304
)这个文件没有变化,你可以继续使用缓存中的资源,并且更新expires
和cache-control
,让这个文件再次缓存服务器设置的时间。如果有变更了,则把新的资源重新返回给客户端(code 200
),客户端重新缓存新的资源。
缓存清除
在html文件中使用meta标签,设置http-equiv
属性和相关的值,来模拟HTTP响应头的一些指令和控制缓存行为。
html
// 资源立即过期
<meta http-equiv="Expires" content="0" >
// 模拟HTTP响应头中的"Pragma"字段,指示浏览器不要缓存该页面。
<meta http-equiv="Pragma" content="no-cache" >
// 模拟HTTP响应头中的"Cache-Control"字段,指示浏览器不要缓存该页面。
<meta http-equiv="Cache-control" content="no-cache" >
// 浏览器应立即将此资源视为过期
<meta http-equiv="Cache" content="no-cache" >
使用webWorker轮询
安装worker-loader 插件
解决思路参考:juejin.cn/post/718545...
总结
强缓存不适合于静态页面的缓存, 如果页面都缓存了,当测试环境资源包更新了,我们访问也是走的缓存数据,这样看不到最新的内容了
可以通过webpack,抽离第三方插件以及图片等静态资源(将其进行缓存),将开发的HTML页面后缀拼上哈希值,这样每次打包,生成的资源名字不一样,则浏览器就会重新从服务器中请求数据。
如果没有进行分包操作,会使浏览器默认将资源进行缓存,这时候可以使用协商缓存或者meta标签处理缓存冗余的问题。