网站CSS、js更新后客户浏览器缓存问题、需要刷新才能正确显示的解决方案。
前端开发中可能出现的问题,更新了在线项目,用户的浏览器显示了上一页,我们没有及时获取更新的资源,这是为什么?为什么此时用户刷新页面可以获得更新的资源?
答案是浏览器缓存
浏览器缓存是前端优化的重要问题,缓存提供了很多好处。
(1)减少冗馀数据传输,节省带宽。
(2)减轻服务器的请求负担,如果有缓存,可以少向服务器发送请求。尤其是对访问量大的一些网站来说,更为重要。
(3)资源从缓存中读取,无需向服务器发送请求和等待返回,从而加快客户端访问速度。
但是缓存同样给前端带来了一个很严重的问题,就是上面所说的项目更新的问题。如果项目更新了,但是用户访问时浏览器读取的是缓存资源,那么用户就获取不到最新的页面,影响用户使用。
接下来就从浏览器缓存开始分析出现项目更新问题的原因,并给出相应的解决方法。
浏览器缓存主要指http缓存,其机制是根据http报文的缓存标识进行相应操作。
一、http状态码
在讨论浏览器缓存之前,我们先看看网页相关的http状态码,打开控制台,在Network下捕捉请求,注意Status和Size栏,会看到200 from disk cache,200数值大小。
刷新页面,会看到,304 数值大小,200 from memory cache。
这几个有什么不同呢?200和304是常见的两个http状态码,200表示文件发生改动,304表示文件未改动,都是服务器返回告知的。在上面两张图中,我们注意到,有些200是灰色的,灰色的200表示没有向服务器发送请求,而是直接从缓存中读取。从缓存中读取又分为从内存(from memory cache)中读取还是从磁盘中读取(from disk cache)。
总结一张表。
200 from memory cache | 状态码是灰色的,从内存中读取之前已经加载过的资源,不请求服务器,页面关闭时,资源就会被内存释放,再次打开相同页面不会出现此类情况,在同一页面刷新才会出现。一般脚本、字体、图片会存在内存当中 |
200 from disk cache | 状态码是灰色的,从磁盘中读取之前已经加载过的资源,不请求服务器,页面关闭不会被释放,这部分资源存在电脑磁盘里,只有用户手动清除浏览器缓存的时候才会释放。一般非脚本会存在内存当中,如css等 |
200 数值大小 | 从服务器下载最新资源,数值是从服务器获取的全部资源大小 |
304 数值大小 | 访问服务器,发现资源没有更新,使用本地资源。数值是与服务器通信报文的大小,并不是资源本身的大小。 |
浏览器有三级缓存原理
1、先查找内存,如果内存中存在,从内存中加载;
2、如果内存中未查找到,选择硬盘获取,如果硬盘中有,从硬盘中加载;
3、如果硬盘中未查找到,那就进行网络请求,加载到的资源缓存到硬盘和内存;
结合我们的问题,假设某个用户打开过我们的页面,然后我们更新了文件,用户再去访问,资源加载情况是200 from disk cache,浏览器根本没有请求服务器,所以拿不到新的资源文件。那么,有没有办法解决这种情况?浏览器缓存机制是什么样的?
二、浏览器缓存
浏览器缓存分两种:强制缓存和协商缓存(对比缓存)
1、强制缓存
强制缓存就是,用户第一次访问页面之后,浏览器将数据存在缓存中,在过期时间之内,都不会再请求服务器。是否使用强制缓存在于资源是否过期,该过期时间从第一次请求的服务器响应头中获取。如果在过期时间内,从缓存中读取,如果超出过期时间,则使用协商缓存(下面会讲)。
控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。
上面的200 from memory cache和200 from disk cache属于强制缓存。
2、协商缓存
协商缓存,从字面意思,就是要协商,是浏览器和服务器协商,那么浏览器每次都要和服务器通信。在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。
与协商缓存有关的字段是Last-Modified/IF-Modified-Since、Etag/IF-None-Match。
Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
强制缓存和协商缓存的具体参数及分析比较可以参考以下文章
再回到我们的问题,用户打开浏览器发现是旧的资源,于是手动刷新了一下页面,得到了新的资源,这是为什么呢?
3、用户行为会对缓存产生影响
结合上面的内容,我们可以分析情况了
1、用户第一次访问页面——200 数值大小,与服务器通信,服务器返回全部资源大小,浏览器把获取到的数据根据缓存规则进行缓存。
2、更新项目,用户打开页面是旧的资源——200 from disk cache,命中强缓存,使用了本地缓存,没有请求服务器
3、用户手动刷新页面,得到新资源——200 数值大小,用户刷新,强缓存失效,使用协商缓存,根据缓存标识发现资源修改了,服务器返回全部新资源和缓存标识
4、用户再刷新页面——304 数值大小,协商缓存,资源没有修改,数值不是全部资源大小,是报文信息大小。同时,这里会出现一些资源200 from memory的情况,它们存在内存中。
我们再看几张图应该就很好理解了
三、解决方法
明白了问题所在,我们接下来就可以提出对应的解决方法了。
以vue为例,vue在打包的时候,css和js名字都加了哈希值,所以改动后打包生成的js和css是唯一的,页面请求的是新资源,不会有缓存问题。但是入口文件index.html会因为缓存造成更新问题,如果我们更新了,但是浏览器使用的是缓存,就会出现问题。所以需要对入口文件设置不使用强制缓存,需要每次去服务器验证文件是否修改,即使用协商缓存。
使用nginx反向代理,在nginx.conf文件的对应server中设置,目前我自己实践出的可行的一种写法是:
server {
listen 80;
server_name 域名;
root 文件目录;
index index.html;
location / { // 不加这一句,会出现nginx欢迎页面,无法正确加载资源
try_files $uri ;
}
location ~ .*\.(html)$ { // 对html文件限制缓存
add_header Cache-Control no-store; // 不缓存
// 或者用add_header Cache-Control no-cache;替代上面那一句,协商缓存
add_header Pragma no-cache;
}
}
(1)Cache-Control: no-cache和Cache-Control: no-store区别
看字面意思容易误解,no-cache就是不缓存,但是no-cache并不是不缓存,而是使用协商缓存,所以并不能禁止缓存,no-store才是真正的禁止缓存。从节省带宽角度讲,使用no-cache更优一点,文件未发生改变时只传输很小的报文大小,只有在文件改变时才会传输整个文件大小。而不是no-store不管什么情况都传输整个文件大小。
(2)Pragma: no-cache:和Cache-Control: no-cache区别
Pragma: no-cache跟Cache-Control: no-cache相同,Pragma: no-cache兼容http 1.0 ,Cache-Control: no-cache是http 1.1提供的。因此,Pragma: no-cache可以应用到http 1.0 和http 1.1,而Cache-Control: no-cache只能应用于http 1.1.
转自:
1.《为什么uc总是缓存错误怎么办看这里!前端项目中 浏览器缓存的更新不及时问题及解决方法》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《为什么uc总是缓存错误怎么办看这里!前端项目中 浏览器缓存的更新不及时问题及解决方法》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/gl/3201705.html