要让静态资源真正“长期可用”且支持离线访问,必须协同nginx缓存与service worker:nginx通过expires或cache-control设置强缓存(如public, immutable, max-age=31536000)并禁用last-modified/etag,配合版本化路径实现边缘与客户端长期缓存;service worker则在install事件中预缓存html、js、css等核心资源,在fetch事件中以cache first策略拦截同源请求,确保离线可用;二者分层协作——nginx加速联网加载,service worker兜底离线场景,关键在于url一致性、哈希化更新机制及缓存存储隔离。

要让静态资源真正“长期可用”且支持离线访问,光靠 Nginx 缓存不够,必须和 Service Worker 协同:Nginx 负责边缘/客户端缓存控制,Service Worker 负责接管请求、管理本地 Cache Storage 并实现离线策略。两者不是替代关系,而是分层配合。
静态资源的 Nginx 长期缓存配置
目标是让浏览器和中间代理(如 CDN)信任这些资源“几乎不变”,从而长期缓存,避免反复校验。关键在于 强缓存头 + 版本化路径:
- 用
expires 1y或add_header Cache-Control "public, immutable, max-age=31536000"——immutable告诉浏览器:该资源不会变,无需发条件请求(如 If-None-Match) - 只对带哈希或版本号的资源启用长期缓存,例如
/static/js/app.a1b2c3d4.js、/images/logo.8f9e7a21.png;避免直接缓存/static/js/app.js这类无版本路径 - 推荐 location 配置示例:
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { alias /var/www/static/; expires 1y; add_header Cache-Control "public, immutable"; add_header Last-Modified ""; etag off; } - 禁用
Last-Modified和ETag:避免浏览器在缓存过期后发起验证请求,破坏“长期”效果
Service Worker 的离线接管逻辑
Nginx 缓存解决的是“重复加载快”,Service Worker 解决的是“没网也能用”。它需主动缓存资源,并在离线时返回:
- 注册时机放在页面首次加载完成之后(避免阻塞),通常在
index.html底部或window.addEventListener('load')中调用navigator.serviceWorker.register('/sw.js') -
sw.js中使用Cache First策略预缓存核心静态资源(HTML、JS、CSS、关键图片):const CACHE_NAME = 'static-v1'; const PRECACHE_URLS = [ '/', '/static/css/main.a2b3c4.css', '/static/js/app.d5e6f7.js', '/images/icon-192.png' ]; <p>self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => cache.addAll(PRECACHE_URLS)) ); });</p><p>self.addEventListener('fetch', event => { if (event.request.destination === 'document') { event.respondWith(caches.match(event.request).then(r => r || fetch(event.request))); } else if (PRECACHE_URLS.includes(new URL(event.request.url).pathname)) { event.respondWith(caches.match(event.request) || fetch(event.request)); } });</p> - 注意:Service Worker 只能拦截同源请求,且
/页面本身必须被缓存(或通过Stale While Revalidate策略兜底),否则首次离线仍白屏
两者协同的关键细节
单独配好任一端都容易失效,以下三点决定是否真正“离线可用”:
-
资源一致性:Nginx 返回的资源 URL 必须与 Service Worker 中
PRECACHE_URLS完全一致(含哈希、大小写、斜杠),否则缓存不命中 -
更新机制:当 JS/CSS 更新时,构建工具生成新哈希文件 → Nginx 自动服务新路径 → Service Worker 检测到新 sw.js(通过
skipWaiting和clients.claim())→ 清除旧缓存并预加载新版资源 -
HTTP 缓存与 Cache Storage 分离:Nginx 的
max-age影响浏览器 HTTP 缓存;Service Worker 的caches.open()管理独立的 Cache Storage。前者加速联网场景,后者兜底离线场景,互不干扰
验证是否生效
打开 Chrome DevTools → Application → Cache Storage,查看对应缓存名中是否有预期文件;再切换到 Offline 模式刷新页面,观察是否正常加载、控制台无 404 或 network error。











