React Native Web集成FCM推送遇Service Worker注册错误求助
首先,你的错误有两个核心原因:Service Worker文件的写法完全不符合Service Worker的运行规则,以及文件没有放在服务器能直接访问的静态资源目录下,导致请求返回HTML(从而出现MIME类型错误)。
一、错误原因拆解
1. Service Worker写法错误
Service Worker运行在独立的后台上下文,没有浏览器的document对象,也不支持ES模块的import语法。你用document.createElement添加脚本、用import * as firebase from "firebase"的写法完全不适用,这会直接导致Service Worker无法正常解析。
2. MIME类型错误根源
当浏览器请求https://localhost:19006/firebase-messaging-sw.js时,服务器没有找到这个文件,于是返回了默认的index.html(MIME类型为text/html),这就是报错的直接原因——浏览器期望加载的是JS脚本,却拿到了HTML。
二、正确的firebase-messaging-sw.js写法
替换你现有的文件内容为以下代码(注意使用importScripts,这是Service Worker加载外部脚本的标准方式):
// 加载Firebase SDK脚本(必须用importScripts,不能用document或ES import) importScripts("https://www.gstatic.com/firebasejs/7.15.0/firebase-app.js"); importScripts("https://www.gstatic.com/firebasejs/7.15.0/firebase-messaging.js"); // 初始化Firebase App firebase.initializeApp({ apiKey: "*********", authDomain: "*********", databaseURL: "*********", projectId: "*********", storageBucket: "*********", messagingSenderId: "1772528518", appId: "*********", }); // 获取Messaging实例,处理后台消息 const messaging = firebase.messaging(); // 可选:如果需要处理后台消息的自定义逻辑,可以添加以下代码 // messaging.setBackgroundMessageHandler(function(payload) { // console.log('[firebase-messaging-sw.js] Received background message ', payload); // const notificationTitle = 'Background Message Title'; // const notificationOptions = { // body: 'Background Message body.', // icon: '/firebase-logo.png' // }; // return self.registration.showNotification(notificationTitle, notificationOptions); // });
三、正确的文件放置位置
1. Expo Web项目
将firebase-messaging-sw.js放在项目根目录下的public文件夹中(如果没有public文件夹,直接创建一个)。Expo Web会将public目录下的文件作为静态资源,服务器可以直接访问到https://localhost:19006/firebase-messaging-sw.js。
2. 纯React Native Web项目
如果是使用react-native-web搭建的项目,通常需要将文件放在项目根目录的public文件夹(对应webpack配置中的静态资源目录),确保webpack会将这个文件复制到构建输出目录的根路径下,这样浏览器就能直接请求到它。
四、额外配置注意事项
- 确保Firebase SDK版本一致:你的前端代码中使用的Firebase版本要和Service Worker中
importScripts的版本(7.15.0)保持一致,避免版本不兼容问题。 - 本地开发的HTTPS问题:Firebase Messaging要求在HTTPS环境下运行(localhost除外,浏览器允许localhost使用HTTP),Expo Web默认的
localhost:19006是符合要求的。 - 前端初始化Messaging时的配置:在你的React Native Web代码中,初始化Messaging时需要指定Service Worker的路径(如果放在根目录,直接用
'/firebase-messaging-sw.js'):import firebase from 'firebase/app'; import 'firebase/messaging'; firebase.initializeApp({ /* 你的配置 */ }); const messaging = firebase.messaging(); messaging.useServiceWorker(navigator.serviceWorker.register('/firebase-messaging-sw.js'));
内容的提问来源于stack exchange,提问作者sagar

