进阶
发布于
完成本指南后,应用会在浏览器支持的地方提供 Web Push、文件访问、后台同步与图标角标,在不支持的地方只失去那一项功能,而不是整个页面。每项能力都用同一个三段式模式包裹:一次特性检测、一个先于增强写好的回退分支,以及发布前在本站查一次兼容性。请先完成入门、让它可安装与离线策略;这里的每项能力都假定已注册 Service Worker 且 manifest 可安装。
把能力闸门只写一次
Section titled “把能力闸门只写一次”把检测放进一个模块,让界面、Service Worker 与埋点对「什么可用」有一致的答案。闸门读取的是对象图而不是 User-Agent,每项能力的回退是一个具体动作,而不是一个被禁用的按钮:
export const capabilities = { push: 'serviceWorker' in navigator && 'PushManager' in window && 'Notification' in window, fileSystemAccess: 'showOpenFilePicker' in window, backgroundSync: 'serviceWorker' in navigator && 'SyncManager' in window, badging: 'setAppBadge' in navigator,};
export const fallbacks = { push: () => showEmailDigestOptIn(), // 用服务端邮件摘要代替推送 fileSystemAccess: () => showDownloadAndUpload(), // <a download> 加 <input type="file"> backgroundSync: () => retryQueueOnNextLoad(), // 在 'online' 事件时冲刷 IndexedDB 队列 badging: () => showUnreadCountInTitle(), // document.title = `(3) Field Notes`};
export function withCapability(name, enhanced) { return capabilities[name] ? enhanced() : fallbacks[name]();}API 存在只是必要条件,不能证明功能对某个用户可用:iOS Safari 的浏览器标签页里有 PushManager,但 WebKit 只向添加到主屏幕的 Web 应用授予推送(iOS 与 iPadOS 16.4,2023-03)。每个闸门都要配上本站对应的兼容性条目,并读它的备注列。
在用户手势之后接入 Web Push
Section titled “在用户手势之后接入 Web Push”web.dev 的推送概览把工作分成三步:请求权限并订阅的客户端代码、负责发送的服务端代码,以及接收并显示通知的 Service Worker 代码。权限请求必须跟在点击之类的手势之后;WebKit 对主屏幕 Web 应用的要求相同。用你的 VAPID 公钥订阅(web.dev:“the combination of the private and public key is known as the application server keys”):
async function enablePush(vapidPublicKey) { if (!capabilities.push) return fallbacks.push(); const permission = await Notification.requestPermission(); if (permission !== 'granted') return fallbacks.push(); const registration = await navigator.serviceWorker.ready; const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: vapidPublicKey, }); await fetch('/api/push/subscribe', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(subscription), });}订阅对象中的 endpoint 指向浏览器厂商的推送服务;web.dev 把它的域名描述为 “essentially the push service”,路径则是客户端标识。把整个订阅对象存在服务端,发送返回 404 或 410 时删除它。在 Service Worker 里,push 监听器调用 self.registration.showNotification();收到推送却什么都不显示的处理器会被视为静默推送,浏览器不允许这样做。
用同样的方式守护文件访问与后台同步
Section titled “用同样的方式守护文件访问与后台同步”showOpenFilePicker() 让编辑器类应用读写用户选中的文件;回退是每个浏览器都支持的一对,<input type="file"> 负责读,<a download> 负责写。Background Sync 让 worker 在网络恢复时重放离线期间的写入;回退是把队列放在 IndexedDB 里,在 online 事件或下次页面加载时冲刷。两者都通过 withCapability() 调用,让两个分支在源码里挨在一起,回退路径就不会悄悄腐坏。
在 DevTools 中测试增强路径
Section titled “在 DevTools 中测试增强路径”Chrome 的 Service workers 面板有 Push 与 Sync 链接,无需服务器即可向活动 worker 派发 push 与 sync 事件,让你在后端尚不存在时先验证接收侧。用 Offline 确认排队的写入在刷新后仍在,并在取消勾选后被重放。
- Web Push
- File System Access
- Background Sync
- 角标
- 按特性查看兼容性
- Push notifications overview(web.dev)
- Web Push for Web Apps on iOS and iPadOS(webkit.org)
← 返回指南总览。