Safari中Service Worker推送通知无法打开新窗口问题求助
Safari中Service Worker推送通知点击不打开新窗口的解决方案
问题根源
Safari对clients.matchAll的客户端URL格式处理、clients.openWindow的调用限制与Chrome存在差异,导致严格的URL匹配逻辑失效,以及openWindow未按预期触发新窗口打开。
修复方案
1. 宽松化客户端URL匹配逻辑
避免严格匹配末尾斜杠,改用URL对象对比源和路径,适配Safari的URL格式差异:
self.addEventListener('notificationclick', (event) => { const data = event.notification.data; const targetUrl = new URL(data.url || 'http://localhost:3356'); console.log({ data, targetUrl: targetUrl.href }); event.notification.close(); event.waitUntil( (async () => { const clientList = await self.clients.matchAll({ type: 'window', includeUncontrolled: true, }); console.log('total clients: ', clientList.length); // 遍历客户端,匹配同源同路径的窗口 for (const client of clientList) { const clientUrl = new URL(client.url); console.log({ clientUrl: clientUrl.href }); if (clientUrl.origin === targetUrl.origin && clientUrl.pathname === targetUrl.pathname && 'focus' in client) { return client.focus(); } } // 尝试打开新窗口 if (self.clients.openWindow) { console.log('Opening a new window', targetUrl.href); const newWindow = await self.clients.openWindow(targetUrl.href); if (!newWindow) { console.log('Failed to open new window in Safari'); } return newWindow; } console.log('No clients to focus'); })() ); });
2. 适配Safari的clients.openWindow限制
- 确保目标URL属于Service Worker的注册范围(
scope),如果你的Service Worker注册在根路径(/sw.js),则范围默认是根,无需额外配置;如果是子路径,需确保目标URL在该范围内。 - 使用
async/await重构代码,更清晰地处理Promise链,避免潜在的Promise回调问题。
3. 额外排查点
- 确认Safari已开启“允许网站请求发送通知”权限,且Web App已被允许推送。
- 检查Service Worker是否处于激活状态,可通过Safari开发者工具的“Service Workers”面板验证。
- 确保目标URL是完整的绝对路径(包含
http/https),避免相对路径导致的解析问题。
内容的提问来源于stack exchange,提问作者Carlos Sosa
相关产品推荐
相关产品推荐

