HTML5 离线存储

发布于:2025-07-14 ⋅ 阅读:(17) ⋅ 点赞:(0)

HTML5 离线存储(通常指 Application Cache)是早期用于实现 Web 应用离线访问的技术,但由于其设计缺陷已被废弃。现代 Web 开发中,取而代之的是更强大的 Service Worker + Cache API 方案(属于 Progressive Web Apps 技术栈)。下面详细解析两者:


一、已被废弃的 Application Cache (AppCache)

1. 基本原理
  • 通过一个 manifest 清单文件(如 app.manifest)声明需要缓存的资源。
  • 浏览器根据清单下载资源并存储在离线缓存中。
2. 使用步骤
<!-- 在 html 标签中声明 manifest 文件 -->
<html manifest="app.manifest">

app.manifest 文件示例

CACHE MANIFEST
# v1.0.0  → 版本号(更新缓存需修改此号)

CACHE:    # 需要缓存的资源
/css/style.css
/js/app.js
/images/logo.png
/index.html

NETWORK:  # 必须在线访问的资源(白名单)
/api/
/login

FALLBACK: # 离线时替代方案
/offline.html     # 所有失败请求的兜底页面
/images/ /images/offline.png # 特定路径的替代
3. 主要问题(被废弃原因)
  • 更新机制不透明:必须修改 manifest 文件(如版本号)才能触发更新。
  • 白名单机制死板NETWORKFALLBACK 规则难以维护。
  • 缓存污染风险:一旦缓存失败,可能导致整个应用无法使用。
  • 无细粒度控制:无法编程式管理缓存。
  • 并发问题:多标签页同时更新可能冲突。

⚠️ 现代浏览器已移除支持(Chrome 70+、Firefox 46+ 等弃用)。


二、现代方案:Service Worker + Cache API

核心优势
  • 完全可编程:通过 JavaScript 精细控制缓存逻辑。
  • 后台运行:独立于主线程,不阻塞页面渲染。
  • 拦截网络请求:可自定义缓存策略(如网络优先/缓存优先)。
1. 实现步骤
(1) 注册 Service Worker
<!-- 在页面中注册 -->
<script>
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(reg => console.log('SW 注册成功'))
    .catch(err => console.error('SW 注册失败', err));
}
</script>
(2) 编写 Service Worker 脚本 (sw.js)
// 定义缓存名称(版本更新时修改此名)
const CACHE_NAME = 'my-app-v1';

// 需要预缓存的资源
const PRE_CACHE = [
  '/',
  '/index.html',
  '/css/main.css',
  '/js/app.js',
  '/images/hero.jpg'
];

// 安装阶段:预缓存关键资源
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(PRE_CACHE))
  );
});

// 激活阶段:清理旧缓存
self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(name => {
          if (name !== CACHE_NAME) return caches.delete(name);
        })
      );
    })
  );
});

// 拦截请求:自定义缓存策略
self.addEventListener('fetch', event => {
  event.respondWith(
    // 策略1:缓存优先(适用于静态资源)
    caches.match(event.request)
      .then(cachedResponse => {
        if (cachedResponse) return cachedResponse;
        
        // 策略2:网络请求并缓存(适用于动态内容)
        return fetch(event.request)
          .then(response => {
            // 只缓存成功响应
            if (!response || response.status !== 200) return response;
            
            const responseToCache = response.clone();
            caches.open(CACHE_NAME)
              .then(cache => cache.put(event.request, responseToCache));
              
            return response;
          });
      })
  );
});
2. 关键特性
功能 实现方式
预缓存 install 事件中使用 cache.addAll()
动态缓存 fetch 事件中通过 cache.put() 缓存网络响应
缓存策略 可自由实现:缓存优先/网络优先/增量更新等
缓存清理 activate 事件中删除旧缓存
离线回退 fetch 事件中返回兜底内容(如离线页面)
3. 常用缓存策略
// 1. 缓存优先(适合静态资源)
caches.match(request).then(cached => cached || fetch(request))

// 2. 网络优先(适合频繁更新数据)
fetch(request).catch(() => caches.match(request))

// 3. 增量更新(先返回缓存,再更新缓存)
event.respondWith(caches.match(request));
event.waitUntil(
  fetch(request).then(response => cache.put(request, response))
);
4. 调试与更新
  • 调试:Chrome DevTools → Application → Service Workers
  • 更新机制
    1. 修改 Service Worker 文件(即使1字节变化)
    2. 新 SW 安装后处于 waiting 状态
    3. 通过 skipWaiting() 强制激活或关闭所有页面后生效

三、最佳实践

  1. 仅缓存必要资源:避免占用过多存储空间。
  2. 设置缓存过期:定期清理旧缓存。
  3. 提供离线回退:如返回离线页面或默认图片。
  4. 结合 IndexedDB:存储结构化数据(如用户设置)。
  5. 使用 Workbox:Google 官方库,简化 Service Worker 开发:
import {precacheAndRoute} from 'workbox-precaching';
precacheAndRoute([...]); // 自动生成缓存清单

四、浏览器兼容性

  • Service Worker:Chrome 40+、Firefox 44+、Edge 17+、Safari 11.1+
  • Cache API:同 Service Worker 支持范围
  • 安全要求:必须使用 HTTPS(本地开发允许 localhost

总结对比

特性 Application Cache (废弃) Service Worker + Cache API
控制粒度 声明式(manifest文件) 编程式(JavaScript)
更新机制 手动修改 manifest 文件内容变化自动更新
请求拦截 ❌ 不支持 ✅ 完全控制网络请求
后台同步 ❌ 不支持 ✅ 支持后台同步(Background Sync)
缓存策略灵活性 极低 极高(可自定义逻辑)
现代浏览器支持 已废弃 广泛支持

💡 现代 Web 离线存储应优先使用 Service Worker,它提供了更强大、灵活的离线能力,是 PWA(渐进式 Web 应用)的核心技术之一。


网站公告

今日签到

点亮在社区的每一天
去签到