HTML的manifest属性已完全失效,Chrome 94+、Firefox 84+、Edge 94+、Safari 16.4+均彻底移除Application Cache支持,浏览器静默忽略该属性,不发起请求、不报错、不缓存;唯一有效替代方案是Service Worker。

HTML 的 manifest 属性已失效,现代浏览器(Chrome 94+、Firefox 84+、Edge 94+、Safari 16.4+)完全移除了 Application Cache 支持,任何依赖 manifest 的离线逻辑在当前环境下都不会触发缓存行为。
为什么 manifest 在 HTML 中不再起作用
从 2022 年起主流浏览器陆续废弃 applicationCache API,并在近两年彻底删除。即使你写对了 <html manifest="app.manifest">,浏览器也不会发起对 app.manifest 的请求,window.applicationCache 在控制台中直接为 undefined,所有相关事件(如 updateready、cached)均不会触发。
常见错误现象包括:
- 页面首次加载后断网,刷新即白屏或 404,而非显示
offline.html - Network 面板里完全看不到
app.manifest请求 - DevTools 的 Application → Cache Storage 或 Frames → Manifest 标签页为空或不可见
cache.manifest 文件结构本身已无实际执行意义
虽然你仍可写出语法正确的清单文件,但浏览器不再解析它。典型内容如:
立即学习“前端免费学习笔记(深入)”;
CACHE MANIFEST # v2.1.0 CACHE: /index.html /style.css /app.js NETWORK: /api/ FALLBACK: / /offline.html
这些内容不会被读取,更不会影响资源加载路径或离线 fallback 行为。尤其注意以下几点:
-
CACHE MANIFEST开头行只是历史遗留格式要求,现在不校验也不生效 -
#注释行曾用于版本控制(改注释强制更新),现在改一百遍也无用 -
FALLBACK规则不会拦截请求,/→/offline.html这类映射完全被忽略 -
NETWORK: *不再阻止缓存,也不影响 Service Worker 的 fetch 控制逻辑
服务器 MIME 类型配置(text/cache-manifest)已成冗余操作
过去必须在 Nginx 或 Apache 中显式设置 .appcache 或 .manifest 的 Content-Type,否则浏览器拒绝处理。现在即使你漏配、配错、甚至返回 404,也不会报错——因为根本没人去请求它。
例如 Nginx 中这段配置已无必要:
location ~ \.appcache$ {
add_header Content-Type text/cache-manifest;
}如果你在日志里还看到 app.manifest 的 200 请求,那大概率是旧版爬虫、测试脚本或未升级的嵌入式 WebView(如某些 Android 7–9 的系统浏览器),不是当前桌面或移动 Chrome/Firefox/Safari 的行为。
真正能替代 manifest 的只有 Service Worker
所有需要离线能力的新项目必须用 ServiceWorker 实现,它通过 navigator.serviceWorker.register() 注册,用 fetch 事件精细控制缓存策略。关键差异在于:
-
manifest是声明式、全局、粗粒度的;ServiceWorker是命令式、可编程、按需缓存 -
cache.addAll()可动态决定缓存哪些资源,支持版本化缓存名(如v2-cache) -
fetch事件中可判断event.request.destination类型,区分图片、脚本、API 请求并分别处理 -
CacheStorage允许清理旧缓存、原子切换、甚至跨域资源缓存(配合 CORS)
一个最小可行离线兜底示例(sw.js):
self.addEventListener('fetch', e => {
if (e.request.destination === 'document') {
e.respondWith(
fetch(e.request).catch(() => caches.match('/offline.html'))
);
}
});这段代码比整个 manifest 体系更可控,也更容易调试和演进。
真正容易被忽略的是:很多老项目上线时只改了 HTML 和 manifest 文件,却没意识到服务器日志里早已没有 manifest 请求;而开发者还在反复修改注释行试图“触发更新”——这本质上是在和一个已不存在的机制较劲。



















