
Web 推送通知允许网站向用户发送即时消息,即使浏览器处于关闭状态。其基本流程涉及以下几个关键组件:
尽管上述工作流程在 Chrome、Firefox、Android 浏览器等平台上通用,但 iOS Safari 对 Web 推送功能施加了一个重要的限制:Web 推送通知仅适用于已添加到主屏幕的 Web 应用程序(PWA)。这意味着,如果用户只是在 Safari 浏览器中访问您的网站,即使他们授予了通知权限,后端发送的推送通知也无法被 Service Worker 接收并显示。
这一限制是由 Apple 的设计哲学决定的,旨在将 Web 推送能力与原生应用体验更紧密地结合,鼓励用户将网站作为“应用”来使用。
前端代码是 Web 推送的基础,负责 Service Worker 的注册、权限请求以及将订阅信息发送到后端。
// service-worker-registration.js (在主页面中加载)
import convertVapidKey from 'convert-vapid-public-key';
window.addEventListener('load', async () => {
// 1. 注册 Service Worker
if (!('serviceWorker' in navigator)) {
console.warn('[Service Worker] Service Worker 在当前设备或环境中不可用!');
return;
}
let registration;
try {
registration = await navigator.serviceWorker.register(window.serviceWorkerPath, {
scope: '/'
});
console.info('[Service Worker] 注册成功:', registration);
} catch (error) {
console.warn('[Service Worker] 注册失败:', error);
return;
}
// 2. 订阅通知
if (
!window.webpushServerKey || // VAPID 公钥
!('Notification' in window) ||
!('PushManager' in window)
) {
console.warn('[WebPush Client] Web 推送在当前设备或环境中不可用!');
return;
}
try {
if (await Notification.requestPermission() === 'granted') {
await subscribe();
// 成功订阅后,可以立即发送一个前端通知进行确认
await registration.showNotification('恭喜!?', {
body: '您已成功订阅通知!?'
});
}
} catch (error) {
console.warn('[WebPush Client] 订阅失败:', error);
}
async function subscribe() {
try {
// 客户端订阅
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: convertVapidKey(window.webpushServerKey)
});
// 将订阅信息发送到后端存储
await fetch('/webpush/', {
method: 'POST',
mode: 'cors',
credentials: 'include',
cache: 'default',
headers: new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json'
}),
body: JSON.stringify({ subscription })
});
console.info('[WebPush Client] 订阅成功:', subscription);
} catch (error) {
console.warn('[WebPush Client] 订阅失败:', error);
}
}
});上述代码展示了标准的 Service Worker 注册和推送订阅流程。其中,window.webpushServerKey 是您的 VAPID 公钥,用于验证推送请求的合法性。前端成功订阅后,会向后端发送 PushSubscription 对象,后端应将其存储在数据库中。
Service Worker 负责在接收到推送通知时进行处理和显示。
// sw.js (Service Worker 文件)
self.addEventListener('push', event => {
try {
const json = event.data.json(); // 解析推送数据
const title = json.title || '';
const options = json.options || {};
console.info('[Service Worker] 收到推送事件:', json);
// 使用 event.waitUntil 确保通知在 Service Worker 终止前显示
event.waitUntil(self.registration.showNotification(title, options));
} catch (error) {
console.warn('[Service Worker] 推送通知处理失败:', error);
}
});这个 push 事件监听器是所有 Web 推送通知的核心。当推送服务将通知发送到设备时,它会触发此事件。Service Worker 解析收到的数据(通常是 JSON 格式),然后调用 showNotification 方法显示通知。
后端使用存储的订阅信息和 VAPID 密钥来构建并发送推送请求。许多语言都有成熟的 Web Push 库可以使用。例如,在 PHP 中,可以使用 bentools/webpush-bundle 这样的库:
<?php use BenTools\WebPushBundle\Model\Message\PushNotification; use BenTools\WebPushBundle\Sender\PushMessageSender; /** @var PushMessageSender $sender */ protected $sender; // ... // 假设 $notification 是一个包含通知标题和内容的自定义对象 // $subscriptions 是从数据库中获取的用户订阅对象数组 $message = new PushNotification($notification->getTitle(), [ PushNotification::BODY => $notification->getBody(), // 可以添加更多选项,如 icon, image, badge, actions, data 等 // PushNotification::ICON => 'path/to/icon.png', // PushNotification::DATA => ['url' => 'https://your-app.com/path'], ]); // 发送通知 $this->sender->push($message, $subscriptions); ?>
后端负责构建符合 Web Push 协议的消息体,并将其发送到推送服务。VAPID 密钥用于对请求进行签名,确保其合法性。
如前所述,iOS Safari 上的 Web 推送通知必须在网站被用户添加到主屏幕后才能正常工作。如果您的网站没有被添加到主屏幕,即使 Service Worker 注册成功,权限也已授予,后端发送的通知也无法触发 Service Worker 中的 push 事件。
解决方案的核心在于引导用户将您的网站添加到主屏幕。
总之,要在 iOS Safari 上成功实现后端发送的 Web 推送通知,关键在于理解并满足其“添加到主屏幕”的先决条件。通过清晰的用户引导和正确的实现,您可以为 iOS 用户提供与原生应用相似的通知体验。
以上就是深入理解 iOS Safari Web 推送通知:从后端发送的限制与解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号