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

聊聊web前端的缓存问题

1. 浏览器缓存机制

强缓存

  • 相关HTTP头:Cache-Control(优先级高)和 Expires
  • 常见指令:max-age(缓存时间)、no-cache(跳过强缓存)、no-store(完全禁用缓存)
  • 示例:Cache-Control: max-age=3600 表示资源缓存1小时

协商缓存

  • 相关HTTP头:ETag(文件哈希)和 Last-Modified(最后修改时间)
  • 流程:浏览器发送请求时携带 If-None-Match(对应ETag)或 If-Modified-Since(对应Last-Modified),服务器返回 304 表示资源未变更
  • 对比:ETag 比 Last-Modified 更精准(避免1秒内多次修改的问题)

2. 缓存位置

  • Memory Cache:内存缓存,快速但生命周期短(随Tab关闭释放)
  • Disk Cache:磁盘缓存,容量大但读取较慢
  • Service Worker Cache:通过Service Worker拦截请求,实现离线缓存(PWA核心)
  • Push Cache:HTTP/2推送的资源缓存,优先级最低

3. 缓存策略实践

  • 静态资源(JS/CSS/图片):设置长期强缓存(如 max-age=31536000),并通过文件名哈希解决更新问题(如 app.a3b4c5.js
  • HTML文件:使用 no-cache 或短 max-age,确保及时更新
  • 动态接口:通常用 no-storemax-age=0

4. 如何保证资源更新?

  • 文件名哈希:Webpack配置 output.filename: '[name].[contenthash].js'
  • 覆盖式发布:先部署新资源,再更新HTML引用

5. Service Worker缓存

  • 生命周期:install(预缓存)、fetch(拦截请求)、activate(清理旧缓存)
  • 代码示例:
self.addEventListener('install', e => {e.waitUntil(caches.open('v1').then(cache => cache.addAll(['/app.js'])));
});
self.addEventListener('fetch', e => e.respondWith(caches.match(e.request)));

Vue3相关的缓存优化

1. 组件缓存:<keep-alive>

  • 作用:缓存动态组件状态,避免重复渲染
  • 生命周期钩子:onActivated(激活时触发)和 onDeactivated(离开时触发)
  • 示例:
<keep-alive include="HomePage"><component :is="currentComponent" />
</keep-alive>

2. 编译优化:静态提升

静态节点提升:将静态节点提取到渲染函数外,避免重复创建

// 编译前(Vue2)
render() { return h('div', null, h('p', null, 'Static Text')) }
// 编译后(Vue3)
const hoisted = h('p', null, 'Static Text');
render() { return h('div', null, hoisted) }

事件侦听器缓存:缓存内联事件处理函数,避免重复生成

// 编译前
render() { return h('button', { onClick: () => foo() }) }
// 编译后
const cachedFn = () => foo();
render() { return h('button', { onClick: cachedFn }) }

3. v-memo指令(Vue 3.2+)

  • 作用:按条件缓存子树,避免不必要的VDiff
  • 适用场景:长列表或复杂计算组件
  • 示例:
<div v-memo="[value]"> <!-- 仅当value变化时才更新 -->{{ expensiveCalculation() }}
</div>

4. 响应式系统优化

Proxy代替defineProperty:
  • 无需递归初始化,性能更高
  • 支持数组/对象动态属性的监听
响应式API细粒度控制:
  • shallowRef/shallowReactive:浅层响应式(避免深层递归开销)
  • markRaw:标记对象跳过Proxy代理

5. 异步组件 + Suspense

异步加载组件减少首屏体积:
import { defineAsyncComponent } from 'vue';
const AsyncComp = defineAsyncComponent(() => import('./Foo.vue'));
<Suspense>处理加载状态:
<Suspense><template #default><AsyncComp /></template><template #fallback>Loading...</template>
</Suspense>

6. 性能陷阱规避

  • 避免滥用响应式:大型非响应式数据用 shallowRef
  • 计算属性缓存:用 computed 替代方法调用,减少重复计算
  • 列表渲染优化:为 v-for 添加稳定 key,避免全量Diff

如何设计一个前端项目的缓存策略?

答:HTML用协商缓存,静态资源用强缓存+哈希文件名,API接口用 Cache-Control: no-store。通过Service Worker实现离线缓存。

keep-alive 的原理是什么?

答:通过Vue的抽象组件实现,缓存组件的VNode实例。激活时复用实例并触发 onActivated,避免重复渲染。

Vue3为什么比Vue2性能更好?

答:通过Proxy响应式、编译时优化(静态提升/PatchFlag)、Tree-shaking支持等,减少运行时开销。

协商缓存中ETag和Last-Modified的区别?

答:ETag通过文件哈希标识内容变化,精度高;Last-Modified依赖时间戳,可能因时间精度或内容不变修改导致失效。

http://www.dtcms.com/a/314784.html

相关文章:

  • 金融专业高分简历撰写指南
  • k8s集群
  • 网络与信息安全有哪些岗位:(5)网络安全工程师
  • SpringCloud (4) 分布式事务
  • Western Blot(蛋白质免疫印迹)--实验操作015
  • 室内液体撒漏泄漏识别分割数据集labelme格式2576张1类别
  • 朴素贝叶斯(Naive Bayes)完整解析:概率论经典算法
  • Scrapy 工作流程深度解析:引擎驱动的完美协作
  • API接口的应用及重要性
  • Nestjs框架: @nestjs/config 配置模块详解与实践
  • 鸿蒙开发-端云一体化--云存储
  • Python-初学openCV——图像预处理(七)——模板匹配、霍夫变换
  • 注解知识学习
  • 腾讯混元重磅开源:四款小尺寸模型全面发布
  • 文件包含篇
  • elementPlus的el-switch在初始化时会调用一次change事件
  • CCLink转ModbusRTU网关控制除湿机配置案例—PLC组态篇
  • AI大模型的基本知识
  • 如何解决GIT合并冲突问题
  • Python----大模型(量化 Quantization)
  • SimpleDateFormat早期Java 日期格式化工具详解
  • 强干扰下车位识别准确率↑28%!陌讯时序建模方案在充电桩占位检测的实战解析
  • 数据结构与算法:哈希函数的应用及一些工程算法
  • Git基础玩法简单描述
  • AR技术赋能能源勘探:从数据可视化到智能预测的革命性突破
  • AR技术赋能轨道交通培训:虚实结合提升学习效率
  • NumPy 重要知识点总结
  • Anthropic的商业模式与战略
  • 2.4- WPF中非 UI 线程上安全地更新 UI 控件方法
  • QT之QLocalSocket下的两进程互相守护