探索声明式 Web Push:WebKit 的新实践
Meet Declarative Web Push
2025 年 3 月 27 日 作者:Brady Eidson
目录:
- The status quo
- How to use Declarative Web Push
- A note on backwards compatibility
- What if I can’t send the notification description through the internet?
- Standards work
Web Push 通知是 Web 平台强大且重要的组成部分。正如一位非常著名的叔叔曾经说过的那样,能力越大,责任越大。当我们将 Web Push 添加到 WebKit 时,我们知道必须维护人们对功效和隐私的期望。 在 macOS 上为 Safari 实施 Web Push,为 iOS 和 iPadOS 上保存到主屏幕的 Web 应用程序以及 Mac 上的 Web 应用程序,我们采取了一种谨慎的方法来维持这些期望。我们知道运行额外的代码来显示通知可能会影响电池续航时间。我们知道 Web Push 对 service worker JavaScript 的依赖与我们在 Web 上对用户隐私的广泛方法背道而驰。我们了解到,我们认为用户隐私所必需的保护措施挑战了 Web 开发人员对其他浏览器中 Web Push 的假设。因此,我们挑战自己,为最终用户、Web 开发人员和浏览器提出更好的方案。
Declarative Web Push 允许 Web 开发人员请求 Web Push 订阅并显示用户可见的通知,而无需安装 service worker。service worker JavaScript 可以选择性地更改传入通知的内容。与原始 Web Push 不同,如果 service worker 未能显示通知,则不会受到惩罚;在这种情况下,声明式推送消息本身将用作可选 JavaScript 处理步骤失败时的后备方案。
Declarative Web Push 在设计上更节能、更注重隐私。对于 Web 开发人员来说,它更容易使用。并且它与现有的 Web Push 通知向后兼容。
请继续阅读我们对当前 Web Push 工作方式所产生挑战的思考。或者直接跳到如何使用 Declarative Web Push。您可以在 iOS 和 iPadOS 18.4 中测试它。
The status quo
现有的 Web Push 通知是在 JavaScript 优先的思维模式下设计的。远程推送不是直接描述用户可见的通知,而是由网站的 service worker JavaScript 处理更抽象的“推送消息”概念。
网站首先需要注册一个 service worker。然后,它可以使用该 ServiceWorkerRegistration
创建一个 PushSubscription
,从而为网站提供远程向浏览器发送推送消息所需的信息。
为了让用户拥有直接控制权,WebKit 要求您作为开发人员始终显示通知;不允许静默推送消息。因此,我们要求推送订阅将 userVisibleOnly
标志设置为 true
。虽然这可能会令人沮丧,但原始 Web Push 设计使其成为保护用户隐私和电池寿命的必要条件。
一旦设备收到推送消息,浏览器就会确保存在 service worker JavaScript 实例,然后向其分派 PushEvent
。处理该事件的代码会检查推送消息中的数据,并使用它来调用 ServiceWorkerRegistration.showNotification(...)
以显示用户可见的通知。
虽然一些流行的 JavaScript 库抽象出了一些复杂性,但其中涉及大量代码,并且许多事情可能会微妙地出错。
Challenge 1 — Silent push protection
回想一下,WebKit 要求在注册推送订阅时将 userVisibleOnly
标志设置为 true。ServiceWorker 的 PushEvent
处理程序中的 JavaScript 负责显示该用户可见的通知。允许网站远程唤醒设备以进行静默后台工作是侵犯隐私的行为并消耗能量。因此,如果事件处理程序由于任何原因未显示用户可见的通知,我们将撤销其推送订阅。
不幸的是,service worker 脚本中的错误、网络状况或本地设备状况都可能阻止及时调用 showNotification
。这些情况可能并不总是脚本作者的错,并且可能难以调试。如果对 userVisibleOnly
承诺进行技术强制执行,因此可以忽略静默推送惩罚箱,那就更好了。
Challenge 2 — Tracking data
我们之前对此进行过博客,并且我们会再次对此进行博客;隐私是一项基本人权。
自 Safari 的第一个版本以来,我们就专注于隐私。WebKit 超越了 Web 标准要求的隐私保护。随着 Web 平台的发展,我们保护用户隐私的策略也在不断发展。这现在包括主动阻止和删除网站数据,例如使用 Intelligent Tracking Prevention(缩写为 ITP)。
ITP 会删除您一段时间未访问过的网站的所有网站数据。这包括 service worker 注册。虽然这可能会让 Web 开发人员感到沮丧,但这是保护用户隐私的关键。考虑到我们对保护用户的承诺,这是一个我们有意做出的艰难权衡。
当我们实施 Web Push 时,这造成了一个难题。由于创建和使用推送订阅本质上与拥有 service worker 相关联,因此 ITP 删除 service worker 注册会使推送订阅变得无用。由于强大的反跟踪预防功能似乎从根本上与现有 Web Push 的 JavaScript 驱动性质相矛盾,那么如果没有 JavaScript 也可以传递 Web Push 通知不是更好吗?
那么,Declarative Web Push 在实践中是什么样的呢?
How to use Declarative Web Push
要使用任何形式的 Web Push,首先需要使用 PushManager
获取推送订阅。Apple 平台上的 Web Push 使用相同的 Apple Push Notification 服务,该服务为所有 Apple 设备上的本机推送提供支持。您无需成为 Apple Developer Program 的成员即可使用它。
原始 Web Push 唯一可用的 PushManager
是 ServiceWorkerRegistration.pushManager
。Declarative Web Push 还公开了 window.pushManager
,以支持订阅管理,而无需 service worker。
const subscription = await window.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: arrayForPublicKey
});
如果您还注册了一个范围限定为网站域根级别的 service worker,则它与 window 对象共享相同的推送订阅。但是,删除该 service worker 注册不会影响关联的推送订阅。
向该推送订阅发送推送消息的工作方式与以前完全相同。为了以声明方式处理通知,推送消息的内容必须与声明式标准 JSON 格式匹配。这种标准化格式保证浏览器有足够的信息来显示用户可见的通知,而无需任何 JavaScript。
{
"web_push": 8030,
"notification": {
"title": "Webkit.org — Meet Declarative Web Push",
"lang": "en-US",
"dir": "ltr",
"body": "Send push notifications without JavaScript or service worker!",
"navigate": "https://webkit.org/blog/16535/meet-declarative-web-push/",
"silent": false,
"app_badge": "1"
}
}
顶级 "web_push"
值是对 RFC 8030 – 使用 HTTP 推送的通用事件传递的致敬。这是选择将推送消息的其余部分用于声明式解析的神奇值。
"notification"
值是一个字典,用于描述浏览器中用户可见的通知。与您在 JavaScript 中以编程方式创建通知时一样,需要一个非空的 "title"
值。还可以指定 NotificationOptions 字典 的大多数可选成员。
到目前为止,我们主要讨论的是在没有 JavaScript 的情况下自动显示通知。当用户激活声明式通知时,在没有 JavaScript 的情况下需要发生一些有用的事情。这就是所需的 "navigate"
值发挥作用的地方。它描述了一个 URL,该 URL 将在激活时由浏览器导航到。
最后,如果 Web 应用程序支持在支持 Badging API 的类似应用程序的模式下运行,例如 iOS 上的主屏幕 Web 应用程序,则声明式消息可以包含更新的应用程序徽章。
A note on backwards compatibility
在实践中,绝大多数 Web Push 消息已经是 JSON。它们描述了要显示的用户可见的通知。处理这些推送消息的 service worker JavaScript 只需解析 JSON 即可以编程方式显示通知。但是,这些 JSON 消息的格式因网站而异。
大多数应用程序会发现以声明式标准 JSON 发送推送消息并重写其 service worker 的 PushEvent
处理程序以显示它非常简单。完成这两个步骤后,这些 Web Push 消息将与尚不支持 Declarative Web Push 的浏览器向后兼容。
如果您的推送消息到达较新的浏览器,则浏览器会以声明方式处理它。如果它到达较旧的浏览器,则它会像以前一样由 JavaScript 以命令式处理。
始终标准化声明式标准 JSON 的一个不错的副作用是引入了所有项目之间的一致性,从而进一步减轻了多产 Web 开发人员的维护负担。
What if I can’t send the notification description through the internet?
所有应用程序(无论其平台如何)可能都无法通过推送服务发送通知的可见内容。通知应如何显示通常取决于用户设备本地的应用程序状态。也许用户已经以服务器尚未意识到的方式使用了该应用程序,需要更新通知。或者,也许该应用程序用于安全通信,并且通知有效负载的解密密钥仅存在于设备上的应用程序中。
在这些情况下,需要代码来处理传入的推送消息以显示有意义的内容。
遇到这些边缘情况的本机 iOS 应用程序有一个名为 UNNotificationServiceExtension
的工具 ,它允许一小段应用程序代码响应传入的推送通知而运行。传入的通知始终有足够的内容来显示用户可见的“后备通知”,但是应用程序的通知服务扩展程序有少量时间来查阅应用程序的本地数据存储并提出新的、更有意义的通知。
如果通知扩展程序中存在错误,或者所需的数据不可用,或者某些其他不可预见的情况导致它无法及时显示不同的通知,则将显示原始“后备内容”。
对于具有 Declarative Web Push 的 Web 应用程序,service worker JavaScript 扮演着相同的角色。当 Declarative Web Push 消息到达并且安装了 service worker 时,会像以前一样将推送事件分派给它。
PushEvent
现在具有来自 Declarative Web Push 消息的“建议通知”的上下文。如果事件处理程序正确显示了替换通知,则会忽略建议的通知。如果事件处理程序无法及时显示替换通知,则使用后备通知。
因为始终存在用户可见的通知(因此,隐私破坏性静默推送仍然是不可能的),所以浏览器不必将它们的“静默推送惩罚”应用于 Declarative Web Push 消息。
iOS 还支持卸载未使用的本机应用程序,这释放了应用程序代码使用的存储空间,同时保留了最少的应用程序功能。在这种情况下,UNNotificationServiceExtension
代码已消失,但仍可以为应用程序显示未修改的通知。
这与 Declarative Web Push 通知在用户的 service worker JavaScript 已被用户或 ITP 删除后如何在 iOS 上工作非常相似。修改传入的推送消息不再可能,但仍可以显示未修改的通知。
Standards work
我们对 Declarative Web Push 感到兴奋,并希望它在所有地方都得到支持。
在我们发布 WebKit Declarative Web Push 说明 的前后,我们还在 TPAC 2023 上与其他浏览器供应商和有关方面联系,并提出了 针对 Push API 的问题 来讨论它。虽然标准机构总是会挑剔细节,但该提案的总体目标得到了很好的满足。
2024 年,我们积极地向涉及的各种规范提出提案,并随着有充分理由的反馈意见的出现而更改我们的实施方式:
- 允许通知和操作指定可导航的 URL 针对 Notifications API,使通知能够在最终用户单击它们后无需涉及 JavaScript 即可导航。(作为标准化 Declarative Web Push 的一部分,我们还对 Notifications API 进行了各种编辑更改。)
- 添加 Declarative Web Push 针对 Push API 规范,定义了新的声明式格式。
- 在 Window 上公开 pushManager 针对 Push API 规范,使 Push API API 可以在不需要 service worker 的情况下使用。
我们认为该功能具有足够的基础,可以让我们发布它并让 Web 开发人员开始尝试它。我们预见到这种坚实的基础可以实现未来的增强功能。我们希望它最终能很快广泛可用。
我们鼓励您通过 WebKit 的 Slack 或我们的 问题跟踪器 与我们联系,以分享您使用这个伟大的新功能的经验。 NextItem Flow, Part 1: A new unified concept for layoutLearn more PreviouslyRelease Notes for Safari Technology Preview 215Learn more