前端缓存那些事

简介: 前端缓存指的是,浏览器对服务器最近请求过的资源进行存储,通过这种方式来达到减少与服务器的交互请求,以此减少对带宽流量的浪费,以及减少了服务器的负担,而浏览器缓存主要分为两种,强缓存和协商缓存

微信截图_20220511173207.png


前端缓存指的是,浏览器对服务器最近请求过的资源进行存储,通过这种方式来达到减少与服务器的交互请求,以此减少对带宽流量的浪费,以及减少了服务器的负担,而浏览器缓存主要分为两种,强缓存和协商缓存


1.强缓存


强缓存所谓的“强”,在于强制让浏览器按照一定时间范围内来存储来自服务器的资源,有点强制的味道~,强缓存是利用Expires或者Cache-Control,不发送请求,直接从缓存中取,请求状态码会返回200(from cache)


1.1 Expires(已逐步淘汰)


Expires是HTTP/1.0中提及的,让服务器为文件资源设置一个过期时间,在多长时间内可以将这些内容视为最新的,允许客户端在这个时间之前不去检查,MDN 具体介绍 点此


  • 指定到期时间


指定缓存到期GMT的绝对时间,如果expires到期需要重新请求


Expires:Sat, 09 Jun 2020 08:13:56 GMT


1.2 Cache-Control(主要)


相比上一小节讲的 expires,两者有什么区别呢? Cache-Control 你可以理解成为高级版expires,为了弥补Expires的缺陷在Http1.1协议引入的,且强大之外优先级也更高,也就是当Expires和Cache-Control同时存在时,Cache-Control 会覆盖Expires的配置,即Cache-Control ( Http 1.1 ) > Expires ( Http 1.0 )


Cache-Control 比Expires比较要内涵,具备更多的属性,其中包括如下


• no-cache :可以在本地缓存,可以在代理服务器缓存,需要先验证才可使用缓存

• no-store : 禁止浏览器缓存,只能通过服务器获取

• max-age : 设置资源的过期时间(效果与expires一样)


例子演示:


// 设置缓存时间为1年
Cache-Control: max-age=31536000
Expires:Sat, 09 Jun 2020 08:13:56 GMT //同时设置两个,Expires会失效


则意味着浏览器可以缓存一年的时间,无需请求服务器,同时如果同时声明Expires和Cache-Control,Expires将失效


🤔️你可能会有疑惑Cache-Control no-cache与max-age=0有什么区别?


本质上就是你按浏览器刷新与强制刷新的区分,看下一节


1.3 用户对浏览器的操作


相信你离不开的操作就是F5(刷新按钮),但是不同的刷新操作意味着不同的反应


• Ctrl + F5 (强制刷新)::request header多了cache-control: no-cache (重新获取请求)


• F5 (刷新)/ctrl+R刷新::request header多了 cache-control: max-age=0 (需要先验证才可使用缓存,Expires无效)


2.协商缓存


协商缓存,就没有强缓存那么霸道,协商缓存需要客户端和服务端两端进行交互,通过服务器告知浏览器缓存是否可用,并增加缓存标识,“有事好好商量”,两者都会互相协商。 协商缓存,其实就是服务器与浏览器交互过程,一般有两个回合,而协商主要有以下几种方式:


2.1 Last-Modified (Http 1.0)


• 第一回合:当浏览器第一次请求服务器资源时,服务器通过Last-Modified 来设置响应头的缓存标识,把资源最后修改的时间作为值写入,再将资源返回给浏览器


• 第二回合:第二次请求时,浏览器会带上 If-Modified-Since 请求头去访问服务器,服务器将 If-Modified-Since 中携带的时间与资源修改的时间对比,当时间不一致时,意味更新了,服务器会返回新资源并更新Last-Modified,当时间一致时,意味着资源没有更新,服务器会返回304状态码,浏览器将从缓存中读取资源


//response header 第一回合
Last-Modified: Wed, 21 Oct 2019 07:28:00 GMT
//request header 第二回合
If-Modified-Since: Wed, 21 Oct 2019 07:29:00 GMT 


2.2 Etag (Http 1.1)


MDN中提到ETag 之间的比较,使用的是强比较算法,即只有在每一个字节都相同的情况下,才可以认为两个文件是相同的,而这个hash值,是由对文件的索引节、大小和最后修改时间进行Hash后得到的,而且要注意的是分布式系统不适用,了解更多点我


• 第一回合: 也是跟上文一样,浏览器去请求服务器资源,不过这次不是通过Last-Modified了,而是用Etag来设置响应头缓存标识。Etag是由服务端生成的,然后浏览器会将Etag与资源缓存


• 第二回合:  浏览器会将 Etag 放入 If-None-Match 请求头中去访问服务器,服务器收到后,会对比两端的标识,当两者不一致时,意味着资源更新,会从服务器的响应读取资源并更新Etag,浏览器将从缓存中读取资源,当两者一致时,意味着资源没有更新,服务器会返回304状态码,浏览器将从缓存中读取资源


//response header 第一回合
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
//request header 第二回合
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"


对比完 Last-Modified 与 Etag,我们可以很显然看到,协商缓存每次请求都会与服务器发生“关系”,第一回合都是拿数据和标识,而第二回合就是浏览器“咨询”服务器是否资源已经更新的过程。


同时,如果以上两种方式同时使用,Etag 优先级会更高,即 Etag( Http 1.1 ) > Last-Modified ( Http 1.0 )


3.缓存状态码


3.1 状态码200 OK(from cache)


这是浏览器没有跟服务器确认,直接用了浏览器缓存,性能最好的,没有网络请求,那么什么情况会出现这种情况?一般在expires或者 Cache-Control 中的max-age头部有效时会发生


3.2 状态码304 Not Modified


是浏览器和服务器“交流”了,确定使用缓存后,再用缓存,也就是第二节讲的通过Etag或Last-Modified的第二回合中对比,对比两者一致,则意味资源不更新,则服务器返回304状态码


3.3 状态码 200


以上两种缓存全都失败,也就是未缓存或者缓存未过期,需要浏览器去获取最新的资源,效率最低 一句话:缓存是否过期用:Cache-Control(max-age), Expires,缓存是否有效用:Last-Modified,Etag


4.缓存的应用


讲述缓存在我们开发中最常见的使用


4.1 Vue中缓存的应用


• keepAlive


vue官方文档提到,当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题,这个时候我们希望那些标签的组件实例能够被在它们第一次被创建的时候缓存下来,我们可以用一个  元素将其动态组件包裹起来 官方文档🚀


主要用于保留组件状态或避免重新渲染,也意味着不会再走mounted,beforeDestroy函数,组件将被缓存,不用销毁重新渲染,性能比较好


路由的选择性缓存


// router.js
export default new Router({
routes:[
   { path: '/test',
    name: 'test',
    component: () => import('@/views/test/test.vue'),
    meta: {
      title: '测试',
      keepAlive: true
    }
  },
 // App.vue
 <keep-alive v-if='$route.meta.keepAlive'>
   <router-view></router-view>
</keep-alive>
 <router-view v-if='!$route.meta.keepAlive'></router-view>


组件缓存


<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>


  • 打包加入hash


前端工程化开发,可以使用 Webpack 编译,打包的资源文件路径里自动带有一串随机字符串,称为 hash


在vue cli脚手架中,我们可以通过配置vue.config.js(本质上是配置webpack)来设置编译生成的文件具备hash值,意味着每次打包编译的文件都是唯一的,来防止因为缓存,导致资源没有更新,官方文档🚀


Vue-Cli 3x版本


// vue.config.js
module.exports = { 
  filenameHashing: true,
  chainWebpack: (config) => {
      config.output.filename('[name].[hash].js').end();
  }
}


4.2 Nginx的缓存


• 配置expires


假设我想通过web应用的图片缓存一周,那你可以在nginx中配置如下👇,配置完之后一周之内的资源只会访问浏览器的资源,而不是去请求Nginx


location ~ \.(gif|jpg|jpeg|png)$ {
          root  /var/mywww/html/public/
          expires 7d;  //表示把数据缓存7天,d:天,s:秒,m:分
  }


  • 设置 etag


location ~ \.(gif|jpg|jpeg|png)$ {
          root  /var/mywww/html/public/
          etag  off;  // 默认是开启 on
  }


更多的Nginx学习,可以看我上一篇 《Nginx的那些事》


欢迎指出问题~



相关文章
|
9月前
|
存储 缓存 NoSQL
Redis多级缓存指南:从前端到后端全方位优化!
本文探讨了现代互联网应用中,多级缓存的重要性,特别是Redis在缓存中间件的角色。多级缓存能提升数据访问速度、系统稳定性和可扩展性,减少数据库压力,并允许灵活的缓存策略。浏览器本地内存缓存和磁盘缓存分别优化了短期数据和静态资源的存储,而服务端本地内存缓存和网络内存缓存(如Redis)则提供了高速访问和分布式系统的解决方案。服务器本地磁盘缓存因I/O性能瓶颈和复杂管理而不推荐用于缓存,强调了内存和网络缓存的优越性。
938 47
|
6月前
|
缓存 前端开发 Linux
哇塞!NPM 缓存竟成开发拦路虎?快来掌握清空秘籍,开启前端开发逆袭之旅!
【8月更文挑战第20天】NPM是前端开发中管理依赖的关键工具。有时需清空其缓存以解决版本不一致或包损坏等问题,确保使用最新依赖。可通过命令`npm cache clean --force`强制清空全部缓存,或手动删除各系统下的缓存文件夹。注意清空缓存可能延长后续安装时间,建议事先备份依赖或确保可重新安装。正确管理缓存有助于提升开发效率。
228 1
|
6月前
|
缓存 JavaScript 前端开发
【性能革命!】Vue 3事件监听缓存的奥秘 —— 揭开前端优化的神秘面纱,让应用性能飙升的秘密武器!
【8月更文挑战第7天】随着前端应用日益复杂,性能优化变得至关重要。Vue 3 通过引入事件监听缓存等新特性提升了应用性能。此特性避免了重复注册相同的事件监听器,减少了资源浪费和潜在的内存泄漏问题。在 Vue 3 中,事件监听器首次渲染时注册,并在后续渲染中重用,除非组件状态变更或手动更新。通过一个示例组件展示了如何利用该特性优化性能,包括使用 `watchEffect` 或 `watch` 在状态变化时重新注册监听器。这一机制降低了浏览器负担,减少了内存占用,提高了应用响应速度,尤其对大型应用效果显著。合理运用事件监听缓存能够构建出更加流畅的应用体验。
382 3
|
6月前
|
缓存 前端开发 Java
【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(-Xms512m -Xmx1204m)?
【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(-Xms512m -Xmx1204m)?
|
7月前
|
缓存 算法 前端开发
前端 JS 经典:LRU 缓存算法
前端 JS 经典:LRU 缓存算法
124 0
|
8月前
|
存储 缓存 JavaScript
【前端 - Vue】之 Keep-Alive缓存组件使用语法及原理解析,超详细!
【前端 - Vue】之 Keep-Alive缓存组件使用语法及原理解析,超详细!
|
9月前
|
存储 缓存 前端开发
【Flutter前端技术开发专栏】Flutter中的图片加载与缓存优化
【4月更文挑战第30天】本文探讨了 Flutter 中如何优化图片加载与缓存,以提升移动应用性能。通过使用图片占位符、压缩裁剪、缓存策略(如`cached_network_image`插件)以及异步加载和预加载图片,可以显著加快加载速度。此外,利用`FadeInImage`、`FutureBuilder`和图片库等工具,能进一步改善用户体验。优化图片处理是提升Flutter应用效率的关键,本文为开发者提供了实用指导。
784 0
【Flutter前端技术开发专栏】Flutter中的图片加载与缓存优化
|
9月前
|
存储 缓存 前端开发
学习和理解前端缓存
前端缓存通过存储重复资源提升网页加载速度,减少服务器压力,优化用户体验。它涉及静态资源(如图片、CSS、JS)的HTTP缓存,动态数据(使用`localStorage`、`IndexedDB`)缓存,用户登录态、页面状态管理,以及预加载缓存。实现方式包括HTTP缓存(强缓存、协商缓存),浏览器存储(localStorage、sessionStorage、IndexedDB),Service Worker和Cache API。在项目中,应根据资源特性和需求选择合适的缓存策略。
|
9月前
|
缓存 算法 前端开发
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
260 0
|
9月前
|
存储 缓存 前端开发
开发指南015-前端缓存的信息
平台前端架构启动后,在store里存储了很多信息,可以通过getter取到

热门文章

最新文章

  • 1
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    详解智能编码在前端研发的创新应用
  • 4
    巧用通义灵码,提升前端研发效率
  • 5
    智能编码在前端研发的创新应用
  • 6
    VSCode AI提效工具,通义灵码前端开发体验
  • 7
    大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
  • 8
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 9
    以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
  • 10
    【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线