当前位置: 首页 > news >正文

浏览器http缓存问题

一、什么是浏览器缓存

浏览器将请求过的资源(html、js、css、img)等,根据缓存机制,拷贝一份副本存储在浏览器的内存或者磁盘上。如果下一次请求的url相同时则根据缓存机制决定是读取内存或者磁盘上的数据还是去服务器请求资源文件

缓存通过url来判断,如果url不同则是新的资源。所以我们开发时前端会将一些js、css等文件在后面加hash值来避免资源更新时浏览器仍读取缓存文件,导致需要刷新才能获取新的资源的问题

这种做法虽然解决了js、css等文件的更新,这种加hash的就不在这篇文章说了,具体方法上网查即可,但是对于index.html这样的文件由于不能加hash值,则仍然会存在当资源更新了,但是仍然读取缓存文件的问题。

二、与缓存相关的状态码

200 ok从浏览器下载的最新资源
200 (from memory cache)不进行http请求,直接从浏览器内存中读取的资源,页面关闭,则资源释放,一般一些脚本、图片、文字等会存在内存中
200 (from disk cache)不进行http请求,直接从磁盘中读取的资源,页面关闭,资源仍然存在,除非清除缓存,一般一些非脚本文件会存在磁盘中,例如html、css文件
304 (not modified)请求了服务器,但是由于服务器资源没有更新,所以仍使用内存中的资源

三、缓存相关的http header介绍

http header介绍
cache-controlresponse header or request header;指定缓存机制,优先级最高
expiresresponse header or request header;指定缓存的过期时间(现在浏览器一般设置cache-control,设置expires是为了兼容http1.0)
last-modifiedresponse header;资源的最后修改时间
etagresponse header;资源的唯一标识符
if-modified-sincerequest header;缓存的服务器资源的最后修改时间
if-none-matchrequest header;缓存的服务器资源的唯一标识

1. 强缓存

不会进行http请求,读取的是内存中的资源,直到缓存失效

涉及到的状态码:

  • 200(from memory cache)
  • 200(from disk cache)

涉及到的http header: 

  • cache-control

优先级最高,所有的缓存机制看到 cache-control 都要服从它

强缓存:设置max-age在这个时间内都不进行http请求,从缓存中读取

cache-control描述
no-store请求和相应都不缓存
no-cache协商缓存,相当于cache-control:max-age=0
max-age指定多少秒后资源过期(强缓存)
  • expires

这个是为了兼容http1.0,由于客户端可以修改时间,所以,expires优先级低,缓存策略以cache-control为准

2. 协商缓存

在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。

涉及到的状态码:

  • 304 not modified
  • 200 ok

涉及到的请求头

  • last-modified (响应头)/ if-modified-since(请求头)

当浏览器第一次请求时,服务端返回资源的同时,会在响应头中添加last-modified,表示资源的最后修改时间,浏览器在第二次请求这个url时会在请求头中带上if-modified-since请求头,值为上一次请求的last-modified,用来询问该文件是否被修改过。

但是last-modified时间只能精确到秒,且无法识别出内容没有修改过的文件,只要修改时间变了就算变动,因此有了etag

  • etag(响应头) / ig-none-match(请求头)

etag解决了last-modified的问题,当etag和last-modified同时存在时则以etag为准

nginx的etag计算方式:计算页面文件的最后修改时间,将文件最后修改时间的秒级Unix时间戳转为16进制作为etag的第一部分 计算页面文件的大小,将大小字节数转为16进制作为etag的第二部分。

etag两种类型:

强etag:

不论实体发生多么细微的变化都会改变其值

强ETag表示形式:"22FAA065-2664-4197-9C5E-C92EA03D0A16"

弱etag:

弱 ETag 值只用于提示资源是否相同。只有资源发生了根本改变产 生差异时才会改变 ETag 。这时,会在字段值最开始处附加 W/

弱ETag表现形式:W/"22FAA065-2664-4197-9C5E-C92EA03D0A16"

浏览器第二次请求上次请求过的url时,浏览器会在HTTP请求头添加一个If-None-Match的标记,用来询问服务器该文件有没有被修改。

四、项目遇到的问题

  • 项目上线后用户需手动刷新页面才能获取新的资源

产生原因:http请求没有设置缓存机制(cache-control或者expires),导致浏览器不知道以什么方式缓存。这种情况一般默认为强缓存,强缓存时间根据一定的计算方式获得,在这个时间段内不会进行网络请求,返回的状态码为200(from disk cache)或者200(from memory cache)

解决办法:

 针对不能加hash值又想要随时获取最新资源的html文件,应该设置请求头 cache-control:no-cache,相当于cache-control:max-age=0

  • 奇怪的问题与排查

现象:nginx并没有配置cache-control或者expires,但是有时却不需要刷新就可以返回最新的资源(200 ok),而有时则返回200 from disk cache。

排查:

查看http的header信息,发现差别在if-modified-sine这个请求头上,返回200 ok的请求头会携带if-modified-sine,而返回200 from disk cache的请起头中没有携带if-modified-sine。

查了一些资料终于找到原因,原因如下:

if-modified-sine的值是第一次报文中 last-modified 的值

为什么会有条件请求字段呢?是因为缓存过期了,所以浏览器会从缓存中查找是否有etag、last-modified字段(注意,缓存是缓存的整个报文,而不仅仅是body部分),有的话,就在请求中带上,向服务器发起协商缓存请求。如果服务器发现资源没有改变,就返回304响应,浏览器就知道,本地缓存中的这个数据资源可以继续使用。(304响应是没有body体的,只有头字段等元信息)也就是说,只有在缓存过期的情况下,请求报文中才会有条件请求的相关字段。什么情况下,缓存会过期呢?如下:

  1. cache-control: max-age=0
  2. cache-control: no-cache
  3. 响应报文根本就没有返回任何关于cache有效期的头字段: cache-control / expire / progma 。那么看是否返回了 last-modified ,如果有该header,浏览器可以使用 Heuristic 算法计算出一个通用的缓存时间 (Date - last-modified) * 10% 

第三点原因就是项目中遇到的奇怪现象的解释。

文章借鉴:https://segmentfault.com/q/1010000007008829     浏览器缓存带来的前端项目更新问题及解决方法_浏览器缓存的数据,如果服务器的数据有变化怎么办-CSDN博客

http://www.lryc.cn/news/509791.html

相关文章:

  • 结构化Prompt:让大模型更智能的秘诀
  • 威联通NAS部署openwrt软路由保姆级教程附镜像文件
  • 《计算机网络(第7版)-谢希仁》期末考试复习题和答案(总结整理)
  • windows和mac共享文件夹访问教程
  • 【PPTist】网格线、对齐线、标尺
  • Leetcode3218. 切蛋糕的最小总开销 I
  • ECCV-2024 | 指令不够用、大模型来生成!BEVInstructor:基于BEV感知和大模型的视觉语言导航指令生成
  • 【UE5.3.2 】引擎中安装RiderLink插件
  • 【HarmonyOS 5.0】第十二篇-ArkUI公共属性(一)
  • 京准电钟解读,NTP网络授时服务器如何提升DCS系统效率
  • 4.银河麒麟V10(ARM) 离线安装 MySQL
  • Redis四种模式在Spring Boot框架下的配置
  • Golang的性能监控指标
  • 基于GAN和DenseNett组合的调制信号分类网络(源码)
  • uniapp 项目基础搭建(vue2)
  • 中关村科金外呼机器人智能沟通破解营销难题
  • 【Linux】处理用户输入
  • flask后端开发(1):第一个Flask项目
  • Highcharts 饼图:数据可视化利器
  • 黑马商城项目—服务注册、服务发现
  • 【ES6复习笔记】Map(14)
  • 15-makefile
  • yii2 手动添加 phpoffice\phpexcel
  • 使用 AI 辅助开发一个开源 IP 信息查询工具:一
  • HNUST-数据分析技术课堂实验
  • P3456 [POI2007] GRZ-Ridges and Valleys BFS-连通块思想
  • WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
  • Clickhouse(Centos)
  • Yolo11改进策略:Block改进|使用FastVit的RepMixerBlock改进Yolo11,重参数重构助力Yolo11涨点(全网首发)
  • 微信小程序-基于Vant Weapp UI 组件库的Area 省市区选择