点击FCM推送通知时打开Firebase Service Worker而非目标链接
Firebase Messaging点击通知打开Service Worker文件的问题修复
你的问题核心在于依赖全局变量存储跳转地址,以及通知点击逻辑中的细节错误,导致点击时无法正确打开目标链接,反而打开了Service Worker自身的文件。以下是针对性的修复方案:
问题原因分析
- 全局变量不可靠:Service Worker可能因浏览器资源回收重启,或者多个通知推送时覆盖地址值,导致点击旧通知时获取的是最新地址(或空值),空值会让
clients.openWindow()默认打开Service Worker的URL。 - 通知未携带自定义数据:没有把跳转链接附加到通知实例中,点击时无法直接从通知本身获取正确地址。
- 窗口匹配逻辑不准确:
client.url === '/'的判断过于严格,实际浏览器中的窗口URL是完整路径(如https://www.hotshots123.com/),无法匹配成功,导致每次都打开新窗口。
修复步骤及代码修改
1. 将跳转链接存入通知的自定义数据
在showNotification的配置中添加data字段,把跳转链接存入,确保点击通知时能直接从通知实例获取:
const notificationOptions = { body: body, icon: imgLink, image: imgLink, data: { link: link // 把跳转链接存入通知数据 } };
2. 修改通知点击事件逻辑
从event.notification.data中获取跳转链接,同时优化窗口匹配逻辑:
self.addEventListener('notificationclick', (event) => { console.log('On notification click: ', event.notification.tag); event.notification.close(); // 从通知数据中获取跳转链接,兜底用根路径 const targetLink = event.notification.data.link || '/'; event.waitUntil( clients.matchAll({ type: "window", includeUncontrolled: true }) .then((clientList) => { // 匹配已打开的本站窗口,优先聚焦 for (const client of clientList) { if (client.url.startsWith(self.location.origin + '/') && 'focus' in client) { return client.focus(); } } // 确保链接是完整URL,避免相对路径问题 const fullLink = targetLink.startsWith('http') ? targetLink : self.location.origin + targetLink; if (clients.openWindow) { return clients.openWindow(fullLink); } }) ); });
3. 移除全局变量(可选)
既然已经把链接存入通知数据,全局变量可以移除,避免不必要的作用域问题:
// 删除这一行:let link ="";
完整修复后的Service Worker代码
importScripts('https://www.gstatic.com/firebasejs/9.2.0/firebase-app-compat.js'); importScripts('https://www.gstatic.com/firebasejs/9.2.0/firebase-messaging-compat.js'); firebase.initializeApp( { apiKey: "AIzaSyDfNp4Q3a-aXMItfgt4ZJlDc", authDomain: "hotshoaseapp.com", databaseURL: 'https:ebaseio.com', projectId: "hots069", storageBucket: "hotppspot.com", messagingSenderId: "223156569", appId: "1:269:web:c4d1", measurementId: "G-CXKE" }); const messaging = firebase.messaging(); messaging.onBackgroundMessage(function(payload) { const title = payload.notification.title; const body = payload.notification.body; const link = payload.data.link; const imgLink = payload.data.imgLink; console.log('[Received background message ', title+" "+body+" "+link ); const notificationTitle = title; const notificationOptions = { body: body, icon: imgLink, image: imgLink, data: { link: link } }; self.registration.showNotification(notificationTitle, notificationOptions); }); self.addEventListener('notificationclick', (event) => { console.log('On notification click: ', event.notification.tag); event.notification.close(); const targetLink = event.notification.data.link || '/'; event.waitUntil( clients.matchAll({ type: "window", includeUncontrolled: true }) .then((clientList) => { for (const client of clientList) { if (client.url.startsWith(self.location.origin + '/') && 'focus' in client) { return client.focus(); } } const fullLink = targetLink.startsWith('http') ? targetLink : self.location.origin + targetLink; if (clients.openWindow) { return clients.openWindow(fullLink); } }) ); });
额外注意事项
- 确保推送的
payload.data.link是完整的HTTPS URL(如https://www.hotshots123.com/article/123),如果是相对路径,修复后的代码会自动补全根域名。 - 测试前先刷新页面,确保新的Service Worker激活生效(可在浏览器DevTools的Application -> Service Workers中查看状态)。
内容的提问来源于stack exchange,提问作者Coderz Way
相关产品推荐
相关产品推荐

