什么是双键缓存?我们必须了解的浏览器缓存新规则!

Hello,大家好,我是 Sunday。

昨天有位 训练营的同学 问我:"Sunday 老师,为什么我的静态资源明明缓存了,但换个站点访问,又得重新下载?"

这个本质上就是因为 双键缓存(Double-keyed Caching) 导致的。

所以,咱们今天就来聊聊 双键缓存是什么,它是如何工作的,以及我们应该如何优化?

什么是双键缓存?

传统的浏览器缓存 中,资源的缓存通常是 基于 URL 进行存储的

比如,当我们访问 https://cdn.sunday.com/script.js 时,那么浏览器会缓存这个 script.js,当其他站点也引用这个 URL 时,浏览器直接复用缓存,不需要重新下载

这种传统的缓存方式,就是开始同学所说的:资源一旦缓存,任何站点都可以访问

但这样做有一个巨大的安全隐患------跨站点追踪(Cross-site Tracking)数据泄露风险

例如:

  • 某些网站可以通过检查公共 CDN 资源的缓存状态,来推测用户是否访问过某些网站(比如:广告追踪)。
  • 黑客可以利用缓存投毒(Cache Poisoning)攻击,让用户加载被污染的资源。

为了避免这些安全问题,很多浏览器(比如:Chrome、Firefox)引入了双键缓存机制。

双键缓存的核心规则是: 缓存资源时,不仅考虑 URL,还要考虑 资源是在哪个站点加载的(Origin),也就是 "站点 + URL" 作为缓存的唯一标识

换句话说:

  • 以前 A 站 缓存的资源,B 站 可以直接复用 ✅
  • 现在 A 站 缓存的资源,B 站 需要重新下载 ❌

双键缓存是如何工作的?

双键缓存 = 站点(Origin)+ 资源 URL

让我们用一个例子来理解:

假设你访问了 网页 A网页 A,它们都使用相同的 CDN 资源 https://cdn.sunday.com/script.js

  • 传统缓存(单键缓存)

    • 你在 网页 A 加载 script.js,浏览器缓存该文件。
    • 你访问 网页 B ,浏览器发现它请求相同的 script.js,于是直接从缓存中加载 (减少了网络请求,提高了加载速度)
  • 双键缓存

    • 你在 网页 A 加载 script.js,浏览器缓存它,并标记为 "仅供 网页 A 使用"
    • 你访问 网页 B ,即使请求相同的 script.js,浏览器也会认为它是 一个全新的资源,需要重新下载

不同的站点,即使请求相同的资源,仍然需要分别缓存!

这种方式提升了安全性,但是也会带来最初那位同学的疑惑,就是:资源无法跨站点共享,必须要重复下载了。

所以说:双键缓存虽然带来的"一定的"安全性,但是也带来了不少的问题,比如:

  • 缓存复用率降低 :即使是相同的资源,不同站点仍然需要重新下载
  • 公共 CDN 失去部分优势:以往我们使用 CDN(如 jsDelivr、UNPKG)是为了让多个站点共用缓存,现在效果大大降低。
  • 首次访问成本上升:用户访问某个站点时,即使本地已经缓存了相同的资源,仍然需要重新下载,导致页面首次加载变慢。

如何优化双键缓存影响?

在上面,咱们已经大致了解了双键缓存的原理以及可能会带来的一些影响了,所以最后咱们就来看看如何尽可能的优化这些问题:

1. 利用 Service Worker

Service Worker 可以在客户端拦截请求,并利用 本地缓存 来减少对网络请求的依赖。

例如,我们可以使用 Cache API 将某些资源手动缓存下来,而不受双键缓存的限制:

javascript 复制代码
self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      return response || fetch(event.request);
    })
  );
});

Service Worker 的缓存存储 不受双键缓存的影响,因此对于高频使用的静态资源,可以考虑让 Service Worker 进行管理,而不是完全依赖 HTTP 缓存。

2. 使用 HTTP/3,减少重复请求开销

由于双键缓存的影响,即使同一个用户访问不同网站,公共 CDN 资源也可能 多次下载

但是,如果通过 HTTP/3(QUIC)协议 通过 多路复用0-RTT 连接,可以优化对应的性能问题。

PS:如何检查你的 CDN 是否支持 HTTP/3?

可以在 Chrome DevToolsNetwork 面板中,查看 Protocol 列,如果显示 h3,说明该资源使用了 HTTP/3 进行传输。

3. 预加载关键资源

既然不能完全依赖浏览器缓存,我们可以主动 预加载关键资源

例如,使用 <link rel="preload"> 来预加载字体、脚本或 CSS:

html 复制代码
<link rel="preload" href="https://你的 cdn 地址/fonts/Roboto.woff2" as="font" type="font/woff2" crossorigin="anonymous">

这样可以确保关键资源即使因为双键缓存机制需要重新下载,也能更快地完成加载。

前端训练营:1v1 私教,9 大服务,终身辅导,帮你拿到满意的 offer 已帮助数百位同学拿到了中大厂 offer

相关推荐
AI大模型-小华36 分钟前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子3 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅3 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni3 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学5 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
赵庆明老师5 小时前
Vben精讲:21-详解web-antd:tsconfig.json
前端·json·vim
wc885 小时前
微软EDGE浏览器功能学习
前端·学习·edge
Csvn6 小时前
🎯 原生 `<dialog>` 元素:终于可以扔掉一半的自定义弹窗组件了?
前端
Csvn6 小时前
🎨 CSS @layer:用「层叠优先级」终结样式打架的世纪难题
前端