Angular集成Firebase Cloud Messaging时Service Worker注册失败报错
Angular集成FCM时Service Worker注册失败的解决方法
问题描述
在Angular应用中使用最新Firebase npm包集成Firebase Cloud Messaging(FCM)时,Service Worker注册失败,报错信息:
service worker registration fails-Uncaught SyntaxError: Cannot use import statement outside a module (at firebase-messaging-sw.js:1:1)
实现的firebase-messaging-sw.js代码如下:
import { initializeApp } from "firebase/app"; import { getMessaging } from "firebase/messaging/sw"; const fcmConfig = {}; // 你的Firebase配置对象 const firebaseApp = initializeApp(fcmConfig); const messaging = getMessaging(firebaseApp); onBackgroundMessage(messaging, (payload) => { console.log( "[firebase-messaging-sw.js] Received background message ", payload ); const notificationTitle = "Background Message Title"; const notificationOptions = { body: "Background Message body.", tag: "notification-1", }; self.registration.showNotification(notificationTitle, notificationOptions); }); self.addEventListener("notificationclick", function (event) { event.notification.close(); event.waitUntil( clients .matchAll({ type: "window", }) .then(function (clientList) { console.log(event); for (var i = 0; i < clientList.length; i++) { var client = clientList[i]; if ( client.url == event.notification.data.notification.click_action && "focus" in client ) return client.focus(); } if (clients.openWindow) return clients.openWindow( event.notification.data.notification.click_action ); }) ); }); self.addEventListener("fetch", function (event) {});
问题原因
浏览器默认将firebase-messaging-sw.js识别为普通脚本文件,而非ES模块,因此无法解析import语句,这是报错的核心原因。
解决方法
方式一:改用Firebase CDN脚本引入(推荐)
替换import语法为CDN加载方式,直接使用全局Firebase对象,无需处理模块类型:
importScripts('https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js'); importScripts('https://www.gstatic.com/firebasejs/9.23.0/firebase-messaging-compat.js'); const fcmConfig = {}; // 你的Firebase配置 firebase.initializeApp(fcmConfig); const messaging = firebase.messaging(); messaging.onBackgroundMessage((payload) => { console.log("[firebase-messaging-sw.js] Received background message ", payload); const notificationTitle = "Background Message Title"; const notificationOptions = { body: "Background Message body.", tag: "notification-1" }; self.registration.showNotification(notificationTitle, notificationOptions); }); // 保留原有的notificationclick和fetch监听逻辑 self.addEventListener("notificationclick", function (event) { event.notification.close(); event.waitUntil( clients .matchAll({ type: "window" }) .then(function (clientList) { console.log(event); for (var i = 0; i < clientList.length; i++) { var client = clientList[i]; if (client.url == event.notification.data.notification.click_action && "focus" in client) return client.focus(); } if (clients.openWindow) return clients.openWindow(event.notification.data.notification.click_action); }) ); }); self.addEventListener("fetch", function (event) {});
注意:CDN版本号需与项目中安装的Firebase版本保持一致,避免版本兼容问题。
方式二:将Service Worker标记为ES模块
若坚持使用import语法,需在注册Service Worker时指定模块类型,并确保构建工具正确处理文件:
- 在Angular注册Service Worker的代码中添加
type: 'module':
navigator.serviceWorker.register('/firebase-messaging-sw.js', { type: 'module' }) .then((registration) => { console.log('Service Worker registered:', registration); }) .catch((err) => { console.error('Service Worker registration failed:', err); });
- 在
angular.json的assets数组中添加该文件,确保构建时复制到输出目录:
"assets": [ "src/favicon.ico", "src/assets", "src/firebase-messaging-sw.js" ]
此方式依赖浏览器对ES模块类型Service Worker的支持,旧浏览器可能存在兼容性问题,因此更推荐第一种方案。
内容的提问来源于stack exchange,提问作者sinan
相关产品推荐
相关产品推荐

