HTML5 离线缓存完全指南:Service Worker 与 PWA 离线体验

小飞兽 HTML/CSS 83 次阅读 2026-05-20

Introduction

HTML5 离线缓存技术让 Web 应用在断网状态下依然可以访问,是 PWA(Progressive Web App)的核心技术之一。离线能力的实现经历了 AppCache(已废弃)到 Service Worker 的演进。Service Worker 是一个独立于页面的后台脚本,可以拦截网络请求、缓存资源、推送通知,是现代 Web 应用必备的能力。

Service Worker 基本概念

/* Service Worker 生命周期:
   1. Register(注册)→ 2. Install(安装)→ 3. Activate(激活)*/

/* 1. 在主页面注册 Service Worker */
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered'))
.catch(err => console.error('SW failed:', err));
}

/* 2. sw.js - Install 事件:缓存静态资源 */
const CACHE_NAME = 'v1-static';
const ASSETS = ['/', '/index.html', '/style.css', '/app.js'];

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

缓存策略与 Fetch 拦截

/* 3. sw.js - Fetch 拦截 */
self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request)
            .then(cached => {
                if (cached) return cached;
                return fetch(event.request)
                    .then(response => {
                        if (response.ok) {
                            const clone = response.clone();
                            caches.open(CACHE_NAME)
                                .then(c => c.put(event.request, clone));
                        }
                        return response;
                    })
                    .catch(() => caches.match('/offline.html'));
            })
    );
});

/* 4. sw.js - Activate:清理旧缓存 */
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keys =>
Promise.all(keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k)))
)
);
});

常见缓存策略

/* Cache First(缓存优先):静态资源 */
async function cacheFirst(request) {
    const cached = await caches.match(request);
    if (cached) return cached;
    const response = await fetch(request);
    return response;
}

/* Network First(网络优先):API 数据 */
async function networkFirst(request) {
try {
return await fetch(request);
} catch {
return await caches.match(request);
}
}

/* Stale-While-Revalidate:性能最佳 */
async function staleWhileRevalidate(request) {
const cached = caches.match(request);
const network = fetch(request).then(r => {
caches.open(CACHE_NAME).then(c => c.put(request, r.clone()));
return r;
});
return cached || network;
}

PWA 清单

/* manifest.json - 让网站可安装 */
{
    "name": "绍大技术网",
    "short_name": "Shaoda",
    "start_url": "/",
    "display": "standalone",
    "background_color": "#faf8f5",
    "theme_color": "#8b4513"
}
/* 注意:HTTPS 是 Service Worker 的硬性要求 */

常见问题

    • AppCache 为什么废弃:规则复杂,容易缓存意外内容。Service Worker 提供了完整的编程能力,是替代方案。
    • Service Worker 调试:Chrome DevTools → Application → Service Workers。
    • 更新:新 sw.js install 完成后需要等所有页面关闭才激活(除非 skipWaiting)。

    延伸阅读

  • Workbox:Google 的 Service Worker 工具库