You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Chrome扩展集成FCM报错:messaging/only-available-in-sw问题求助

我之前在Chrome扩展里集成FCM时也踩过几乎一样的坑,给你梳理下问题根源和针对性的解决步骤:

核心问题分析

你遇到的 FirebaseError: Messaging: This method is available in a service worker context. 错误,本质是因为你在传统的background script(background.js)里调用了只能在service worker上下文运行的FCM API(messaging.getToken(),同时你的manifest配置还没切换到service worker模式,导致FCM无法识别正确的运行环境。

另外还有个容易忽略的小问题:你的service worker文件名多了一个n——firebase-messaginng-sw.js 应该改成 firebase-messaging-sw.js,这个拼写错误会直接导致service worker注册失败。


分步解决方案

1. 修正manifest.json的后台配置

Chrome扩展集成FCM必须使用service worker作为后台,不能用传统的scripts数组配置。修改你的manifest:

{
  "permissions": ["tabs", "storage", "notifications"],
  "background": {
    "service_worker": "firebase-messaging-sw.js" // 这里指定service worker文件
  },
  "gcm_sender_id": "103953800507" // 这个值是固定的,FCM要求必须添加,不能修改
}

注意:gcm_sender_id 是Chrome扩展对接FCM的必填项,必须设置为上述固定值,否则无法接收推送。

2. 重构service worker文件(firebase-messaging-sw.js

把所有FCM相关逻辑移到service worker里,包括初始化、获取token、后台消息处理。因为只有这里是合法的service worker上下文:

// 先导入Firebase库(service worker里必须用importScripts)
importScripts('./lib/firebase/firebase-app.js');
importScripts('./lib/firebase/firebase-messaging.js');

// 初始化Firebase
firebase.initializeApp({
  'messagingSenderId': '111111111' // 替换成你的Sender ID
});

const messaging = firebase.messaging();
const VAPID_KEY = "XXXXXX"; // 替换成你的VAPID公钥

// 设置VAPID密钥
messaging.usePublicVapidKey(VAPID_KEY);

// 获取并存储FCM Token的逻辑
async function getAndStoreFCMToken() {
  try {
    const currentToken = await messaging.getToken({ vapidKey: VAPID_KEY });
    if (currentToken) {
      console.log(`Current FCM Token: ${currentToken}`);
      // 把Token存储到Chrome存储,方便扩展其他页面/脚本调用
      await chrome.storage.local.set({ fcmToken: currentToken });
    } else {
      console.log('No token found. Request user notification permission first.');
      // 如果没有Token,通常是用户没授权通知,这里可以触发权限请求
      Notification.requestPermission();
    }
  } catch (err) {
    console.error('Failed to get FCM Token:', err);
  }
}

// 处理后台推送消息
messaging.setBackgroundMessageHandler(function(payload) {
  console.log('[firebase-messaging-sw.js] Received background message:', payload);
  // 自定义通知内容,优先用payload里的数据
  const notificationTitle = payload.data.title || 'Background Message Title';
  const notificationOptions = {
    body: payload.data.body || 'Background Message body.',
    icon: './public/icon.png' // 确保图标路径正确
  };
  return self.registration.showNotification(notificationTitle, notificationOptions);
});

// 页面加载时自动获取Token
getAndStoreFCMToken();

3. 调整原background.js的逻辑

如果你原来的background.js还有其他业务逻辑,不能直接用scripts数组加载了,需要把它集成到service worker里,或者通过消息通信的方式调用:

  • 方式一:在firebase-messaging-sw.js末尾导入background.js
    importScripts('./background.js');
    
  • 方式二:如果background.js里的逻辑需要和service worker交互,用chrome.runtime.onMessage来通信。

4. 权限与测试注意事项

  • 确保用户已经授权通知权限:可以在扩展的弹出页或首次加载时调用Notification.requestPermission()
  • 测试时要使用Chrome的扩展开发者模式,加载已解压的扩展包,查看service worker的控制台(Chrome开发者工具 → Application → Service Workers)。
  • 推送测试时,确保你的FCM服务器端配置正确,使用获取到的Token发送测试消息。

内容的提问来源于stack exchange,提问作者Divyansh Singh

火山引擎 最新活动