html5离线缓存需显式声明manifest文件,满足存在性、内容变更及资源可下载三条件,否则静默失败;已由service worker取代,现代项目应迁移。

离线缓存不是“自动变离线”,而是靠 manifest 文件触发的显式声明
HTML5 的离线缓存(Application Cache)本质是一套**浏览器强制执行的静态资源预加载机制**,不是你加个 manifest 属性就“顺带”缓存了——它必须满足三个硬条件:文件存在、内容变化、且所有声明资源可完整下载。一旦任一资源 404 或跨域,整个缓存过程静默失败,浏览器继续用旧缓存甚至直接报错。
-
manifest文件第一行必须是CACHE MANIFEST,大小写敏感,不能有 BOM - HTML 文件与
manifest文件必须同源(协议+域名+端口完全一致) - 被
CACHE:列出的资源,哪怕只是 HTML 自身,也必须能被浏览器 GET 成功;否则缓存不会建立 - 浏览器只在
manifest文件内容字节级变化时才触发更新,改注释、加空格都算;但改资源文件本身不触发更新
service worker 已取代 Application Cache,但老项目还在用,得知道怎么救
Chrome 94+、Firefox 84+ 已彻底移除 applicationCache API,Safari 从 iOS 16.4 起也标记为废弃。你现在看到的“离线能用”,大概率是 service worker 在兜底,或者用户设备还跑着旧版浏览器。如果维护老项目,别碰 window.applicationCache.update() —— 它在新浏览器里是 undefined,调用直接报错。
- 检查是否启用:
if ('applicationCache' in window),而不是if (window.applicationCache) - 监听事件要用
window.applicationCache.addEventListener('updateready', ...),但注意该事件只在新缓存就绪后触发一次,且需手动swapCache() - 真正可靠的 fallback 是提前注册一个最小 service worker,哪怕只拦截
/index.html并返回cache.match(),也能绕过 AppCache 失效风险
manifest 文件写错一行,整个离线逻辑就瘫痪
Manifest 看似简单,但格式容错率极低。常见失效场景不是代码写错,而是部署或路径细节翻车:
-
NETWORK:下写*是合法的,但 Safari 对通配符支持不稳定,建议明确列出如/api//upload -
FALLBACK:后面两个路径必须同源,且第二个(离线页)必须在CACHE:里声明过,否则离线时 404 - 相对路径以 manifest 文件所在目录为基准,不是 HTML 所在目录;比如
manifest="v2/cache.manifest",那里面写的style.css就是相对于/v2/ - 服务器必须返回
text/cache-manifestMIME 类型,Nginx 需加add_header Content-Type "text/cache-manifest";
离线包 ≠ 离线应用,真要可靠得自己管资源生命周期
Application Cache 是“全有或全无”的粗粒度缓存,没版本灰度、没增量 diff、没校验哈希——它只认 manifest 内容变了没。现代 H5 离线包(如电商首页、活动页)基本都用 ServiceWorker + IndexedDB + zip 解包 自研方案,manifest 只剩历史包袱。
立即学习“前端免费学习笔记(深入)”;
- 想做热更新?AppCache 做不到,每次更新都是全量覆盖,用户得等全部资源下完才能切新包
- 想校验完整性?AppCache 没 hash 字段,篡改一个 JS 文件,浏览器照常执行
- 想控制缓存空间?AppCache 由浏览器统一管理,Android WebView 甚至可能因满 5MB 强制清空
- 真正可控的做法:用
fetch()下载 zip 包 →JSZip解压 → 存进IndexedDB→ SW 拦截请求时查 DB 返回 blob URL
AppCache 的设计初衷是“让简单站点快速离线”,但它对工程化、稳定性、调试性的支持几乎为零。现在还依赖它,等于把缓存逻辑交给了浏览器黑盒——而黑盒,往往只在出问题时才打开。











