跳转到内容

面向 iOS 发布 PWA

发布于

Safari 允许用户把 PWA 添加到 iOS 主屏幕。准备好 manifest 和添加步骤,检测显示模式,并在用户操作后请求通知权限。获得权限还不等于完成推送订阅。

iOS 26 上的 Safari 26 默认将添加到主屏幕的网站作为 Web 应用打开,用户也可关闭 Open as Web App 来创建书签。WebKit 记录了 iOS 与 iPadOS 16.4 主屏幕 Web 应用的 Web Push。它的第三方浏览器添加路径要求具备 Apple 的托管 Web 浏览器 entitlement。

Web 应用 manifest 提供应用名称和图标等安装元数据。display 成员表达首选显示模式, start_url 是浏览器可以忽略的提示。当 manifest 提供图标时,Safari 26 会使用这些图标。

{
"name": "现场笔记",
"short_name": "笔记",
"start_url": "/",
"display": "standalone",
"icons": [
{ "src": "/icons/notes-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/notes-512.png", "sizes": "512x512", "type": "image/png" }
]
}

在文档 head 中使用 <link rel="manifest" href="/manifest.webmanifest"> 链接 manifest。

Apple 的 iPhone 指南要求用户打开 Safari 的分享菜单,选择 Add to Home Screen, 开启 Open as Web App,再选择 Add。当文档不处于独立显示模式时,显示这些操作 说明。

WebKit 说明,iOS 或 iPadOS 16.4 上的主屏幕 Web 应用必须响应直接的用户交互来请求 Web Push 权限。MDN 同样把 Notification.requestPermission() 放在点击处理器中。权限只是其中一步; WebKit 将标准 Web Push 描述为 Push API、Notifications API 和 Service Worker 共同工作。

这些完整页面分别覆盖显示模式分支和权限分支。当所检测的能力或状态不存在时,两者都会 保留可见的回退路径。

在非独立模式中显示 Safari 操作说明

链接到“在非独立模式中显示 Safari 操作说明”一节

用 display-mode 媒体特性判断是否处于独立模式,并在该模式中隐藏说明。在其他显示模式中,有文档 依据的 Safari 路径会保持可见。

<!doctype html>
<html lang="zh-CN">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>安装现场笔记</title>
<p id="install-hint">在 Safari 中打开分享,再选择 Add to Home Screen。</p>
<script>
const installHint = document.querySelector('#install-hint');
const standalone = window.matchMedia('(display-mode: standalone)').matches;
if (standalone) {
installHint.hidden = true;
} else {
installHint.hidden = false;
}
</script>
</html>

MDN 提醒,显示模式并不直接证明安装状态,因此这个示例只用它判断当前视图中是否需要 显示操作说明。

只报告权限请求的结果。如果 Notifications API 不存在或结果不是 granted,页面会保留 应用内更新路径。

<!doctype html>
<html lang="zh-CN">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>现场笔记通知权限</title>
<button id="permission" type="button">请求通知权限</button>
<p id="status" aria-live="polite">可在应用内查看更新。</p>
<script>
const status = document.querySelector('#status');
document.querySelector('#permission').addEventListener('click', async () => {
if (!('Notification' in window)) {
status.textContent = '仍可在应用内查看更新。';
return;
}
const permission = await Notification.requestPermission();
if (permission === 'granted') {
status.textContent = '已获得通知权限。';
} else {
status.textContent = '仍可在应用内查看更新。';
}
});
</script>
</html>

成功文本没有宣称推送已经启用,因为这个示例没有创建 Push API 订阅。