滴滴实习一面:浏览器缓存机制

这是之前一个27同学面滴滴实习的题目,部门是体验平台,针对浏览器缓存问了强弱缓存区别以及使用场景等问题,小圆这边整理好了~

浏览器缓存是前端性能优化中最重要的一环。合理利用缓存,不仅能显著提升页面加载速度、减少服务器压力,还能改善用户体验。但在面试中,很多人只会“Cache-Control、ETag、Expires”这几个名词,却说不清底层逻辑与交互过程。本文讲解浏览器缓存机制,从类型、原理到实践配置,帮你彻底吃透这个高频考点。 

一、缓存的分类概览

浏览器缓存大体分为两类:

类型

是否向服务器发请求

命中后资源来源

常用字段

强缓存(Strong Cache)

本地缓存(Memory/Disk)

Cache-Control

Expires

协商缓存(Negotiated Cache)

服务器返回304,浏览器使用本地缓存

ETag/If-None-Match

Last-Modified/If-Modified-Since

二者的关系可以概括为:强缓存优先,未命中后再进入协商缓存。

二、强缓存机制详解

1. 触发时机

当浏览器请求某个资源时,会先检查本地缓存是否可用(即强缓存是否命中)。

2. 核心字段

(1)Cache-Control

现代浏览器主推的缓存控制头,它的优先级高于 Expires。常见取值如下:

指令

含义

max-age=600

资源在600秒内有效

no-cache

强缓存失效,强制进入协商缓存

no-store

禁止缓存任何内容

public

所有人都可以缓存(CDN、中间代理)

private

仅客户端可缓存,代理服务器不能缓存

(2)Expires

HTTP/1.0 时代的产物,通过绝对时间控制缓存失效,如:

Expires: Wed, 22 Oct 2025 12:00:00 GMT

缺点是依赖客户端时间,易受系统时间差影响。

3. 强缓存的优先级判定

浏览器判断逻辑如下:

if (Cache-Control 存在) → 使用 Cache-Control
else if (Expires 存在) → 使用 Expires
else → 不使用强缓存

四、协商缓存机制详解

当强缓存失效后,浏览器会携带部分资源标识向服务器发起请求,询问资源是否更新。若服务器确认资源未变更,则返回 304 Not Modified,浏览器直接使用本地缓存副本。

1. 核心字段

(1)Last-Modified / If-Modified-Since

  • 服务器首次响应
Last-Modified: Wed, 22 Oct 2025 10:00:00 GMT
  • 浏览器下一次请求时
If-Modified-Since: Wed, 22 Oct 2025 10:00:00 GMT

若服务器判断文件无更新,则返回 304

缺点

  • 时间精度以秒为单位,若文件在一秒内被多次修改,可能检测不到更新。
  • 一些文件周期性重新生成,即使内容相同,时间不同也会触发重新下载。

(2)ETag / If-None-Match

ETag 是资源内容的唯一标识(通常是哈希值)。

  • 服务器首次响应
ETag: "filehash-12345"
  • 浏览器下一次请求时
If-None-Match: "filehash-12345"

若 ETag 一致,则返回 304

优点:精度更高,不依赖时间。缺点:计算 ETag 会增加服务器负担。

一般做法:两组字段(ETag / Last-Modified)常同时使用,保证兼容性与准确性。

五、缓存的整体流程

浏览器加载资源时的完整判断流程如下:

  1. 检查强缓存(Cache-ControlExpires
  2. 发起请求携带验证字段(If-Modified-Since 或 If-None-Match)。
  3. 服务器判断资源是否变动:

六、缓存位置与生命周期

缓存可存在多个层次:

位置

特点

Memory Cache

存在内存中,关闭标签页即失效

Disk Cache

存储于硬盘,可长期存在

Service Worker Cache

可自定义缓存逻辑,离线可用

Push Cache(HTTP/2)

仅连接生命周期内有效

浏览器通常会根据资源类型与大小选择合适的存储位置。

七、实际项目中的应用策略

1. 静态资源(JS/CSS/图片)

  • 使用文件指纹(hash)解决更新问题;
  • 设置长时间缓存:
Cache-Control: max-age=31536000, immutable
  • 文件变更时文件名变化,浏览器自动拉取新版本。

2. 接口请求(API)

  • 频繁变化 → 使用 no-cache 或 no-store
  • GET 接口若数据稳定,可考虑 ETag 提升性能。

3. HTML 页面

  • 通常设置为 no-cache
  • 通过版本号或构建标识控制更新。

总结

前端常用的缓存方案一般采用强缓存与协商缓存相结合的方式,具体是:

1. HTML文档配置协商缓存

2. JS、CSS、图片等资源配置强缓存

这样当项目版本更新时,可以获取最新的页面;若版本未更新,则可以继续复用之前的缓存

八、前端开发者常见误区

  1. 误区1:no-cache 就是不缓存实际上,它只是强缓存失效,仍可能走协商缓存。
  2. 误区2:ETag 与 Last-Modified 互斥它们可以并存,服务器优先验证 ETag,再验证时间。
  3. 误区3:缓存设置全交给后端前端在构建环节(Webpack/Vite)也能配置静态资源 hash 与缓存策略。

总结

浏览器缓存机制是 Web 性能优化的基石。可以用一句话总结它的核心逻辑:先看强缓存(Cache-Control、Expires),再看协商缓存(ETag、Last-Modified)。命中即本地读取,未命中则询问服务器是否更新。

面试时若能把流程、字段、优缺点等等讲清楚,并结合项目实践(比如资源指纹 + CDN 缓存策略),可以给面试官留下好印象哦。

#前端八股文##面试##日常实习##前端##秋招#
全部评论

相关推荐

11-25 17:23
已编辑
门头沟学院 前端工程师
点赞 评论 收藏
分享
12-03 09:24
复旦大学 Java
性格问题,面试之前非常紧张,没有录音,说一下记得的内容8.28一面(95min)1.子类与父类的加载过程,静态方法重写,静态代码块2.Java中sync阻塞与可重入是怎么实现的,轻量级锁这么可重入,重量级锁维护了wait set3.sync锁升级,AQS4.用户态,内核态5.wait与sleep,调用后操作系统发生了什么,sleep是怎样唤醒的6.concurrenthashmap介绍,size()怎么个流程7.单例模式,双重校验锁,volatile机制,可见性原理(MESI),直接将sync加方法上的锁粒度问题,类加载机制的懒汉8.MySQL中select语句执行流程9.事务与并发MVCC10.rr隔离级别下的间隙锁导致的死锁问题11.索引的注意事项12.uuid与自增id,顺序写与随机写,空间占用,可能导致极端情况varchar数据存不下导致的行溢出问题,同时网络消耗(其实这都不重要,能消耗多少)11.mysql能否保证数据不丢失12.事务注解失效的情况,你是怎么避免的,主要说了代理类,吃异常的一些问题13.spring循环依赖解决,两级缓存能否解决,可以,只是需要实例化后都暴露且暴露代理类,三级缓存提供了一个延迟以及按需加载的思想(不知道理解的对不对),判断是否需要加载代理类,以及需要时才提前暴露14.mybatis执行流程,缓存有了解吗,说一下优缺点15.实习问题手撕:链表加法9.3二面(65min)1.聊一下hashmap,负载因子与len = 8锁涉及到的概率问题,树化的优缺点2.介绍concurrenthashmap -> CAS + sync + volatile,主要说一下尽量使用用户态的CAS去尝试,这点再AQS中也有体现(不知道我的理解有没有问题)3.你说了concurrenthashmap 这么多优点,那有没有缺点 -> 主要提了一下并发机制,常见的缓存,MVCC中rc,rr允许读旧数据,尽管volatile无需加锁,但cpu缓存一致性时也存在消耗,可能在读写并发量较高时性能有所缺陷4.MySQLselect语句流程(我真绷不住了,一面问了我没复习)5.MySQL如何解析到select语法错误的,客户端连接时,用户名密码存在错误时MySQL如何解决的6.介绍B+树,主要从多叉有序平衡,树高来说7.你说了B+树有这么多优点,那有没有缺点,这边主要讲了并发量高的insert/delete场景下页分裂时锁整棵树,讲了B-link树的一些优化点,谈到了跳表设计机制8.说一下常用的jdk,1.8的新特性,lambda实现原理,功能性接口9.实习拷打手撕:山峰数组二分找变化点下标补充:简历上的实习内容有些不清楚,还好找同事咨询了,不然也是难绷有保底心态确实会不一样9.6 oc
点赞 评论 收藏
分享
评论
4
11
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务