浏览器缓存带来的前端项目更新问题及解决方法

    先说一个前端开发中会遇到的问题,我们更新已上线的项目,用户的浏览器显示的却是旧版的页面,没有及时获取到我们更新的资源,这是什么原因造成的?此时,如果用户刷新一下页面,就得到更新后的资源,又是为什么?

答案是 浏览器缓存

浏览器缓存是前端优化的一个重要问题,缓存可以带来很多好处:

(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。

    强制缓存和协商缓存的具体参数及分析比较可以参考以下文章:

    [1]. 浏览器的协商缓存与强缓存

    [2]. 10分钟彻底搞懂Http的强制缓存和协商缓存

    再回到我们的问题,用户打开浏览器发现是旧的资源,于是手动刷新了一下页面,得到了新的资源,这是为什么呢?

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 /index.html;

        }

 

        location ~ .*\.(html)$ {  // 对html文件限制缓存

          add_header Cache-Control no-store;  // 不缓存

         // 或者用add_header Cache-Control no-cache;替代上面那一句,协商缓存

          add_header Pragma no-cache;

        }

}

  • 方法二(摘自其他博文,未经过验证)
  1. 最直接的办法
    Internet选项-》Internet临时文件“设置”-》“每次访问此页时检查”,缺点是要设置每台客户端,客户端较多时不可取

  2. 设置网页头(header)

HTML页面:

<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="Mon, 23 Jan 1978 20:52:30 GMT">

ASP页面:

<%
Response.Expires = -1
Response.ExpiresAbsolute = Now() - 1
Response.cachecontrol = "no-cache"
%>

PHP页面:

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");

JSP页面:

<%
response.setHeader("Pragma","No-Cache");
response.setHeader("Cache-Control","No-Cache");
response.setDateHeader("Expires", 0);
%>
  1. 简单有效的办法
    在访问的URL后面拼接随机数作为参数:
var randomNum = Math.random();
url += "&randomNum="+randomNum;


说明:

(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.

    参考文章:

    彻底理解浏览器的缓存机制

 

 

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 浏览器缓存前端开发中常用的优化技术,它可以大大提高网页加载速度和降低服务器压力。 浏览器缓存的工作原理是将网页的静态资源,如图片、CSS、JavaScript等文件存储在浏览器本地,下次访问该网页时可以直接从本地缓存中读取,而不用再向服务器请求,从而大大减少了网络请求时间。 使用浏览器缓存需要在服务器端配置缓存控制,告诉浏览器该资源可以缓存多长时间。这通常是通过设置 HTTP 头部的 Expires 和 Cache-Control 字段来实现的。 注意,浏览器缓存并不适用于所有情况,特别是当网页的内容需要经常更新时,就不适合使用浏览器缓存。此时,应该在服务器端配置为不缓存,以保证用户每次都获取到最新的内容。 总之,浏览器缓存前端开发中一个很有用的优化技巧,它可以提高网页加载速度并降低服务器压力,但也需要根据实际情况进行适当的使用。 ### 回答2: 浏览器缓存前端开发中一个常见但又容易被忽视的重要概念。它可以显著提高网站的加载速度和用户体验。本文将向大家介绍浏览器缓存的基本原理、常见问题以及前端开发中常用的缓存控制方法。 首先,浏览器缓存是一种将已经下载过的资源保存在客户端的技术。当用户再次访问网站时,浏览器可以直接从本地缓存中加载资源,而无需重新下载,从而提高了网站的加载速度。浏览器缓存可以分为两种类型:强缓存和协商缓存。 强缓存是通过设置响应头中的Expires或Cache-Control字段来实现的。Expires字段指定了资源的过期时间,Cache-Control字段可以设置资源在浏览器缓存中存储的时间。当浏览器访问该资源时,在过期时间内,浏览器直接从缓存中加载资源,而不会发送请求到服务器。 协商缓存是通过设置响应头中的Last-Modified和ETag字段来实现的。Last-Modified表示资源的最后修改时间,ETag是资源的唯一标识符。当浏览器再次请求该资源时,会发送If-Modified-Since和If-None-Match字段,服务器会根据这些字段判断资源是否有更新。如果资源未被修改,服务器返回304状态码,浏览器直接从缓存中加载资源,否则服务器返回新的资源。 在前端开发中,我们可以通过使用版本号或者哈希值的方式来解决缓存问题。每当修改了资源文件时,我们可以将资源的链接中加入一个版本号或者哈希值,这样就可以保证每次资源文件发生变化后,链接的变化能够告知浏览器重新下载资源。另外,我们还可以使用工具或者服务器配置来对静态资源进行缓存控制,如使用Webpack的hash命名方式生成文件名,或者在Nginx配置文件中设置缓存时间。 总之,浏览器缓存是一种能够显著提高网站性能的技术。理解浏览器缓存的原理和机制对于前端开发人员来说是非常重要的。通过合理设置缓存相关的响应头、采用合适的缓存策略以及使用版本号和哈希值等方式,我们可以有效控制和利用浏览器缓存,提高网站的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值