浏览器缓存问题

[前端]浏览器缓存问题

  • 缓存问题描述
  • 为什么需要缓存
    • 缓存的优劣
      • 优势
      • 劣势
  • 缓存的使用
    • 流览器的三级缓存原理
    • 缓存出现的场景
  • 缓存的相关概念
    • 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,但文件未变化,所以将使用缓存数据

以上问题都是缓存导致的,那么为什么需要缓存呢,既然会导致数据无法更新等各种问题,为什么还要使用缓存呢?

为什么需要缓存

我们知道一般系统或网页上线之后,如果没有出现更新的情况下,这些静态资源一般是不会发生变化的,那么在每次打开系统的时候重新请求该静态资源就是对网络资源(如是手机网页,就是浪费流量)的浪费,因为之前已经请求过了,所以缓存是很有必要的。

所以就需要一个合适的缓存策略,我们希望数据交互的时候每次都拿到的是最新的数据,不要使用缓存数据;而获取静态资源时,希望当资源发生变更的时获取最新资源,否则使用缓存资源

缓存的优劣

使用缓存有时会导致意想不到的情况发生,就是资源更新后确使用了缓存的未更新的资源,所以我们要避免这种情况的发生

优势

资源访问的时候直接使用客户端(客户端一般情况是浏览器,也可能是桌面版软件)的缓存资源,避免带宽资源的浪费

劣势

若是出现资源的变更,直接使用客户端的缓存资源,会导致不可预测问题

所以希望资源在未发生变更时直接使用缓存资源;若是发生变更希望使用从服务器获取到的变更后资源

缓存的使用

客户端获取资源或数据交互的时候,决定是否使用缓存,是客户端(也即浏览器)判定的

但是以上说法也并不准确,是当资源第一次加载完成后,客户端再次需要该资源的时候,根据资源第一次加载的响应指令和页面指令等设置,决定是否使用使用缓存。

流览器的三级缓存原理

如果客户端需要某个资源:

  1. 先是从客户端缓存存取位置查找内存
  2. 如果内存位置没有需要的缓存资源,然后是查找磁盘,
  3. 若以上位置均没有,就会通过网络查找,也就是去服务端获取资源

缓存出现的场景

资源允许缓存,并且没有资源更新的情况下,查看网页的几种情况:

  1. 打开新窗口
    第一次打开网页,此时浏览器没有缓存信息,资源都是从服务器获取,然后根据缓存策略缓存资源;
    再次打开网页,在谷歌浏览器中所有js/css/image资源都是从Disk Cache中获取

  2. 地址栏回车
    若是第一次访问网页时会访问服务器获取资源;
    非第一次访问网页,在该网页打开的情况下回车,也就是刷新网页,因为加载过资源,所以此时内存中是存在该资源的,所以使用资源的情况是从内存中获取;根据浏览器的三级缓存原理,若是页签关闭,内存中资源会被删除,此时新开页签,输入地址回车,因为内存中没有该资源,因此从Disk Cache中加载

  3. 按浏览器后退按扭
    相当于再次访问网页

  4. 按浏览器刷新按扭
    等同于地址栏回车

缓存的相关概念

http状态码 & size 说明

浏览器缓存问题_第1张图片

网页浏览器第一次加载的状态码与size信息截图;

浏览器缓存问题_第2张图片

上图是一个页面再次加载浏览器信息截图

所以针对状态码与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
}

在浏览器支持的前提下,便可以对其进行增删改查操作。

  1. 首先我们先得打开或者创建数据库:
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 属性一起使用
    • 该指令不能保证数据的隐私性或者安全性。但是其中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中被引入的资源:

  1. 同一个图片,内容变更,但是打包后文件名未变。例如, 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()%>">
    
  1. 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,但是可以看到显示的提示"来自缓存"
    浏览器缓存问题_第3张图片

  • Chrome 截图
    浏览器缓存问题_第4张图片

交互的缓存策略

浏览器缓存问题_第5张图片

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 的缓存方式,但是该方式连部署都失败了,原因还不明白!!

你可能感兴趣的:(前端,前端)