平台中的平台
按版本看 iOS 上的 PWA(iOS 11.3 到 iOS 26)
发布于 更新于
一个 Web 应用在 iPhone 上能做什么,同时取决于 iOS 版本与它附带的 manifest。各版本加入了 service worker、推送、角标以及调整后的存储配额等能力,manifest 成员则会影响其显示模式、图标与标识。本条目给出带日期的清单,以便有依据地选定支持下限,而不是凭感觉。
下面每个版本都改变了站点在运行时能观察到的某件事,只有一处例外:iOS 17.4 一节记录的是一次在欧盟宣布、又在正式版发布前撤回的移除。实际后果是:支持下限是一个关于能力的陈述,而示例中的能力检测就是在不读取用户代理字符串的前提下守住这条下限的办法。
service worker 之前:iPhone OS 1.1.3 与 2.1
Section titled “service worker 之前:iPhone OS 1.1.3 与 2.1”主屏幕图标比这里其他一切都早。WebKit 的 Safari 26.0 功能文章记载,iPhone OS 1.1.3(2008 年 1 月)让用户可以把网站图标添加到主屏幕,点按图标会在 Safari 中打开该网站;iPhone OS 2.1(2008 年 8 月)让开发者可以用 apple-mobile-web-app-capable meta 标签请求类应用的独立模式。这两件事定下了此后每个版本都在调整的格局:添加动作由用户完成,而页面标记只能影响结果。
iOS 11.3:service worker 与 Cache API
Section titled “iOS 11.3:service worker 与 Cache API”service worker 随 11.3 beta 到达 iOS,公布于 Workers at Your Service(2018 年 2 月)。文章明确说明了它们运行的位置:Safari、使用 SFSafariViewController 的应用,以及保存到主屏幕的 Web 应用。它同样明确说明了限制。除规范要求的源分区之外,WebKit 还按顶层文档的源再做一层分区,因此 webkit.org 页面内的 example.com 框架会得到自己的分区。该版本的 Cache API 配额是每个分区固定 50 MiB,一旦用满,需要空间的存储操作就会失败,直到页面自己清理条目。WebKit 还会移除数周未被使用的 service worker 注册,以及数周未被打开的缓存,因此离线优先的应用必须能承受随时失去其中任一项。
iOS 11.4:Web 应用 manifest
Section titled “iOS 11.4:Web 应用 manifest”W3C 于 2013 年开始标准化 Web 应用 manifest,浏览器支持自 2014 年 11 月开始,Safari 则在 2018 年 3 月随 iOS 11.4 采纳该格式,这些时间点来自 Safari 26.0 的文章。从那个版本起,manifest 与 apple-mobile-web-app-capable meta 标签一起成为决定被添加的图标产生 Web 应用还是书签的途径:该文章的说法是,过去 17 年里站点需要具备 meta 标签或 manifest 的 display 值才会以 Web 应用方式打开。这条规则一直持续到 iOS 26 把决定权交给用户。
iOS 15.4:manifest 的读取时机与 manifest 图标
Section titled “iOS 15.4:manifest 的读取时机与 manifest 图标”Safari 15.4 中有两项变化影响 manifest 的读取方式。浏览器改为在页面加载期间获取 manifest,而不是等到用户选择“添加到主屏幕”的那一刻,这也让该文件可以描述在 Safari 中浏览的页面。此外,manifest 中声明的图标开始可用:当 HTML head 中没有定义 apple-touch-icon,且 manifest 的图标条目省略 purpose 或设为 "purpose": "any" 时,Safari 与 iOS 会使用它们。apple-touch-icon 链接仍然优先,这是有意的设计,站点由此可以为 iOS 保留一个与其他移动平台不同的专用图标。
iOS 16.4:推送、角标与 manifest 身份
Section titled “iOS 16.4:推送、角标与 manifest 身份”Safari 16.4 是让已安装 Web 应用可以与应用相提并论的那个版本。它为添加到主屏幕的 Web 应用加入了 Web Push,建立在 Push API、Notifications API 与 service worker 之上,通知会出现在锁定屏幕、通知中心以及配对的 Apple Watch 上,并可通过专注模式配置。它为主屏幕 Web 应用加入了 Badging API,用户允许通知后即自动获得该权限。它加入了对 manifest id 成员的支持,使同一个 Web 应用的多份安装保持可区分。它还让第三方浏览器可以在共享菜单中提供“添加到主屏幕”。
iOS 17:存储配额的重写
Section titled “iOS 17:存储配额的重写”配额数字在 Safari 17.0 以及 iOS 17 上的 WebKit 应用中发生了变化,记载于 Updates to Storage Policy。浏览器应用,即可被设为默认浏览器的应用,获得的单源配额最高为磁盘总空间的 60 %,总体配额最高为 80 %;其他应用分别最高为 15 % 与 20 %。跨源框架位于自己的分区中,配额为主框架单源配额的 10 %。该版本还不再就网站想要更多空间向用户弹窗询问,并带来了对 Storage API 的完整支持,其中 navigator.storage.persist() 依据启发式规则授予,而这些规则包含站点是否以主屏幕 Web 应用打开。独立运行的 Web 应用获得的单源配额与总体配额,与它在浏览器应用中打开时相同,因此安装并不会换来额外空间。
欧盟的 iOS 17.4:宣布移除,随后撤回
Section titled “欧盟的 iOS 17.4:宣布移除,随后撤回”2024 年 2 月,Apple 表示作为遵守《数字市场法》(DMA)的一部分,将为欧盟用户移除主屏幕 Web 应用。它在开发者支持页面上的原话是 “to comply with the DMA’s requirements, we had to remove the Home Screen web apps feature in the EU”,并称欧盟用户将 “through a bookmark with minimal impact to their functionality” 访问网站。给出的理由是:要处理使用其他浏览器引擎的 Web 应用所带来的安全与隐私问题,就得构建 “an entirely new integration architecture”,而 iOS 当时并没有这样的架构。Open Web Advocacy 最早在 iOS 17.4 的第一个 beta 中注意到这一变化,并记录了 Apple 于 2024-02-16 的确认(It’s Official, Apple Kills Web Apps in the EU,open-web-advocacy.org)。
这次移除没有进入正式版。同一页面原文上方加入的更新写明,Apple “will continue to offer the existing Home Screen web apps capability in the EU”,这项支持 “means Home Screen web apps continue to be built directly on WebKit and its security architecture”,受 beta 中移除影响的开发者与用户 “can expect the return of the existing functionality for Home Screen web apps with the availability of iOS 17.4 in early March”(Changes for apps in the European Union,2024-03-04 存档,web.archive.org)。Open Web Advocacy 把撤回日期记为 2024-03-01(Apple backs off killing web apps,open-web-advocacy.org),iOS 17.4 于 2024-03-05 发布(About the security content of iOS 17.4 and iPadOS 17.4,support.apple.com)。对支持下限而言,这段经过不增加新的一行:欧盟保留了原有能力,而且按 Apple 的说法,它仍建立在 WebKit 之上。
iOS 18.4 与 iOS 26:先是声明式推送,再是没有条件的可安装性
Section titled “iOS 18.4 与 iOS 26:先是声明式推送,再是没有条件的可安装性”Safari 18.4 让 Declarative Web Push 在 iOS 与 iPadOS 18.4 上对添加到主屏幕的 Web 应用可用,这是该平台上第一条完全不需要 service worker 的通知路径。随后 Safari 26.0 改变了“添加到主屏幕”的含义:默认情况下每个被添加的网站都以 Web 应用打开,想要浏览器书签的用户在添加时关闭 Open as Web App 即可,文章直白地写明,Safari 中如今对可安装性“零要求”。manifest 仍然有价值,因为其中声明的图标依旧会被使用,而 Safari 26.0 另外接受 SVG 文件与 data URL 作为图标。
两段代码都是针对能力而非版本写的,这也是它们在下一个版本上同样正确的原因。
大规模预缓存前先确认空间
Section titled “大规模预缓存前先确认空间”存储上限在 iOS 17 发生了移动,把假设写死的站点至少会在一个受支持的版本上出错。改为询问,并为无法回答的引擎保留一条路径。
async function roomFor(bytes) { if (!('storage' in navigator) || typeof navigator.storage.estimate !== 'function') { return true; // 这里没有 Storage API:直接尝试写入并处理配额错误。 } const { quota = 0, usage = 0 } = await navigator.storage.estimate(); return quota - usage > bytes;}回退分支返回 true 是诚实的选择:写入仍有可能成功,而调用方在两条分支里都必须处理 QuotaExceededError。把一个无法回答的问题当作拒绝,会在本来能应付的引擎上关掉离线支持。
声明一个所有受支持版本都能用的图标
Section titled “声明一个所有受支持版本都能用的图标”本条目覆盖的版本区间内图标解析方式各不相同,因此两种形式都声明,让各版本自行取用。两者同时存在时 apple-touch-icon 链接胜出,这使它成为可预测的下限。
<link rel="apple-touch-icon" href="/icons/apple-touch-180.png" /><link rel="manifest" href="/manifest.webmanifest" />manifest 依然值得保留:自 iOS 15.4 起,没有 apple-touch-icon 时会使用它的图标;自 iOS 16.4 起,它的 id 让多份安装彼此区分;自 iOS 26 起,它的图标条目可以是 SVG。在 iOS 15.4 及之后的版本中,当 apple-touch-icon 不存在,且 manifest 图标省略 purpose 或其值包含 any 时,系统会使用该 manifest 图标。
过去调试主屏幕 Web 应用的 service worker,是一场与想要检查的那个事件的赛跑。Safari 26.0 取消了这场赛跑,而这条菜单路径值得记下来。
对推送相关的工作而言,真正要紧的是暂停选项,因为它能在足够早的时刻停下执行,让断点落在处理程序内部,而不是它已经返回之后。
- iOS 与 Safari 上的 PWA
- iOS 与 iPadOS 上的 Web Push(16.4+)
- StorageManager.persist() 与 persisted()
- iOS 上主屏 Web 应用的存储隔离
- Workers at Your Service(webkit.org)
- Updates to Storage Policy(webkit.org)
- Apple backs off killing web apps(open-web-advocacy.org)
- WebKit Features in Safari 16.4(webkit.org)
规范
| 规范 | 状态 |
|---|---|
| 无。 | |