浏览器缓存机制

深入理解浏览器缓存的完整体系:内存缓存、Service Worker 缓存、HTTP 缓存,以及在不同场景下如何选择合适的缓存策略。


浏览器缓存的多层架构

浏览器缓存不是单一的一层,而是由多个层次组成:

请求 → Service Worker 缓存
      ↓ 未命中
     → 内存缓存(Memory Cache)
      ↓ 未命中
     → 磁盘缓存(Disk Cache)
      ↓ 未命中
     → HTTP 缓存
      ↓ 未命中
     → 网络请求

内存缓存

内存缓存存储在浏览器进程的内存中。

特点

  • 读取速度极快
  • 容量有限(通常几十 MB)
  • 标签页关闭后消失
  • 浏览器自动管理,开发者无法直接控制

什么进入内存缓存

  • 小文件(通常 < 50KB)
  • 预读取的资源
  • 已经解码的图片

磁盘缓存

磁盘缓存存储在文件系统中。

特点

  • 容量大(几百 MB 到几 GB)
  • 持久化,标签页关闭后仍然存在
  • 读取速度比内存慢

什么进入磁盘缓存

  • 大文件
  • JavaScript、CSS、图片等

Service Worker 缓存

Service Worker 是一种在浏览器和服务器之间的代理,可以完全控制缓存策略:

// sw.js
const CACHE_NAME = 'v1';
const urlsToCache = ['/', '/styles.css', '/script.js'];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => {
      return cache.addAll(urlsToCache);
    })
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      // 缓存命中返回缓存,否则发起网络请求
      return response || fetch(event.request);
    })
  );
});

HTTP 缓存

HTTP 缓存是最常用的缓存机制,通过 HTTP Header 控制:

缓存策略

策略 适用资源 特点
强缓存 不经常变化的静态资源 不发请求,直接用缓存
协商缓存 可能变化的资源 发请求验证是否过期
不缓存 每次都要最新 总是发起请求

强缓存

# Expires(HTTP/1.0,已过时)
Expires: Wed, 21 Oct 2025 07:28:00 GMT

# Cache-Control(HTTP/1.1)
Cache-Control: public, max-age=3600
# public: 可被 CDN 和浏览器缓存
# max-age: 缓存有效期(秒)

协商缓存

# Last-Modified / If-Modified-Since
Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT

# ETag / If-None-Match(更精确)
ETag: "33a64df551425fcc55e4d42a148795d9"

缓存决策流程

请求发起
    ↓
检查 Service Worker 缓存
    ↓ 未命中
检查内存缓存
    ↓ 未命中
检查磁盘缓存
    ↓ 未命中
检查 HTTP 缓存(强缓存)
    ↓ 未过期 → 直接用缓存
    ↓ 已过期 → 发送请求,带上协商缓存的 ETag/Last-Modified
           ↓ 服务器返回 304 → 用缓存
           ↓ 服务器返回 200 + 新内容 → 用新内容,更新缓存

实际缓存策略设计

策略一:长缓存 + 版本化(最佳)

# 文件名带 hash,内容变化时 URL 变化
/app.abc123.js
/style.css?v=2.1.0

# HTTP Header
Cache-Control: public, max-age=31536000, immutable

策略二:HTML 采用协商缓存

# HTML 变化频繁,但需要确保用户拿到最新版本
Cache-Control: no-cache
ETag: "abc123"

策略三:API 数据不缓存

# API 数据实时性要求高,不缓存
Cache-Control: no-store

这一章想说的

浏览器缓存是多层次的:

  1. Service Worker:完全控制缓存策略,适合离线应用
  2. 内存缓存:快速但短暂,适合小文件和预读取
  3. 磁盘缓存:持久但较慢,适合大文件
  4. HTTP 缓存:服务端控制,适用于大多数场景

最佳实践:长缓存 + 版本化——文件名包含 hash,内容变化时 URL 变化,自然避免缓存失效问题。


延展阅读