安装 · 概念
可安装性条件
发布于
可安装性条件是浏览器为页面提供安装入口(地址栏图标、菜单项或 beforeinstallprompt 事件)之前检查的一组条件。Chromium 浏览器(Chrome、Edge、Samsung Internet)要求安全源,外加带有名称、起始 URL、非 browser 显示模式与图标的 manifest;iOS 26 上的 Safari 与 Windows 上的 Firefox 143 完全没有 manifest 要求,任何页面都能从各自菜单安装(BCD html.manifest、Chrome “Changes to the installability criteria”、WebKit Safari 26.0 发布文章、Firefox 143 发行说明)。
Chromium 在页面每次加载时评估,并把结果记录在 DevTools 的 Application › Manifest › “Installability” 下。按 Chrome 可安装性文章列出的顺序,检查项为:
- 页面来自安全上下文:
https:,或开发期间的http://localhost与http://127.0.0.1。 - 文档链接了一个可解析的 manifest(
<link rel="manifest">),其中包含name或short_name、start_url、取值为standalone、fullscreen或minimal-ui的display(或解析到其中之一的display_override),以及包含 192 px 与 512 px 条目的icons;安装对话框还要求至少一个 144 px 以上、PNG、SVG 或 WebP 格式、设置了sizes且purpose包含any的图标。 start_url位于scope内并返回一个文档(重定向到其他源会使检查失败)。- 该应用尚未在当前浏览器配置文件中安装。
带 fetch 处理器的已注册 service worker 曾是清单的一部分,直到 Android 上的 Chrome 108 与桌面端的 Chrome 112 取消了从浏览器菜单安装时的这一要求;Chrome 为没有 service worker 的已安装应用提供默认离线页。同一篇 Chrome 文章指出,beforeinstallprompt 背后的启发式仍然检查 fetch 处理器,所以页面可能通过菜单检查却始终收不到事件。Chrome 还会把事件(以及 Android 的 mini-infobar)推迟到参与度启发式满足之后,这就是 DevTools 面板报告“可安装”而事件不触发的原因。
其他浏览器采用不同的清单:
| 浏览器 | 提供安装之前要求什么 | 安装入口 |
|---|---|---|
| Edge 79+(桌面端) | 与 Chrome 相同的 manifest 与 HTTPS 检查,相同的 Chromium 版本门槛 | 地址栏图标、Apps 菜单、beforeinstallprompt |
| Samsung Internet 9.0+ | Chromium 清单的自有变体;兼容性数据集记录 beforeinstallprompt 自 9.0 起可用 |
地址栏安装按钮、beforeinstallprompt |
| Safari,iOS 与 iPadOS 26 | 无:从共享菜单添加的每个站点都以 web 应用打开,除非用户关闭 “Open as Web App” | 共享菜单 › “Add to Home Screen” |
| Safari,iOS 与 iPadOS 16.4 至 18 | 需要 manifest display: standalone 或 fullscreen(或旧的 apple-mobile-web-app-capable meta 标签)才进入 web 应用模式;否则为书签 |
共享菜单 › “Add to Home Screen” |
| Safari 17+,macOS 14+ | 无;File › “Add to Dock” 对任何页面可用,存在 manifest 时读取其取值 | File 菜单 |
| Firefox 143+,Windows | 无;地址栏图标把任何站点固定为任务栏 web 应用 | 地址栏图标 |
| Firefox for Android | 一个 manifest;安装为主屏幕快捷方式,无事件 | 三点菜单 › “Install” |
对作者而言,权衡在于只有 Chromium 的清单是可能不通过的,所以满足 Chrome 的 manifest 也满足其余各家浏览器的安装路径;反之不成立,只在 iOS 上测试的页面可能缺少 Chrome 对话框需要的图标就上线了。
第一个示例是镜像 Chromium 清单的页面侧检查;第二个是一份能通过检查的 manifest。
按 Chromium 清单检查页面并据结果行动
Section titled “按 Chromium 清单检查页面并据结果行动”页面无法运行 Chrome 的可安装性算法,但可以核对它自己控制的输入,并按浏览器决定提供哪种安装界面。回退分支覆盖那些无需任何这些输入就能安装的浏览器。
async function installabilityReport() { const problems = []; if (!isSecureContext) problems.push('不是安全上下文:没有浏览器会提供安装');
const link = document.querySelector('link[rel="manifest"]'); if (!link) { problems.push('没有 <link rel="manifest">'); } else { const manifest = await fetch(link.href).then((r) => r.json()).catch(() => null); if (!manifest) problems.push('manifest 无法解析'); else { if (!manifest.name && !manifest.short_name) problems.push('manifest 需要 name 或 short_name'); if (!manifest.start_url) problems.push('manifest 需要 start_url'); if (!['standalone', 'fullscreen', 'minimal-ui'].includes(manifest.display)) problems.push('display 不能是 browser'); const sizes = (manifest.icons ?? []).flatMap((i) => (i.sizes ?? '').split(' ')); if (!sizes.includes('192x192') || !sizes.includes('512x512')) problems.push('icons 需要 192x192 与 512x512'); } } if (!('serviceWorker' in navigator)) problems.push('不支持 service worker:离线页不可用'); return problems;}
const problems = await installabilityReport();if (problems.length && 'onbeforeinstallprompt' in window) { console.warn('Chromium 不会触发 beforeinstallprompt:', problems); // 修 manifest} else if (!('onbeforeinstallprompt' in window)) { showMenuInstructions(); // Safari 与 Firefox 不看这份清单,从菜单安装}service worker 那一行只是信息提示:自 Chrome 112 起它的缺失不再阻止安装,但意味着已安装应用显示的是 Chrome 的默认离线页,而不是站点自己的。
一份满足所有浏览器安装路径的 manifest
Section titled “一份满足所有浏览器安装路径的 manifest”下面的 manifest 满足 Chromium 清单;Safari 与 Firefox 会从中读取 name、icons 与 display,但并不要求它们。
{ "name": "Field Notes", "short_name": "Notes", "id": "/notes/", "start_url": "/notes/?source=pwa", "scope": "/notes/", "display": "standalone", "background_color": "#ffffff", "theme_color": "#1f3a5f", "icons": [ { "src": "/notes/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { "src": "/notes/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { "src": "/notes/icons/maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } ]}把 any 与 maskable 两种 purpose 放在不同的图标条目上,对 Chrome 对话框很重要:它需要一个 purpose 包含 any 的图标;写成单条 "purpose": "any maskable" 也能通过检查,但两种场景会渲染同一张位图。
- Changes to the installability criteria(developer.chrome.com)
- What does it take to be installable?(web.dev)
- WebKit features in Safari 26.0(webkit.org)
- beforeinstallprompt 事件
- iOS 添加到主屏幕
- 桌面端安装
iconsmanifest 成员- Firefox
规范
| 规范 | 状态 |
|---|---|
| 无。 | |