React Native裸工程连接Firebase模拟器遇认证网络错误求助
我用裸开发流程做React Native应用,已经搭好带Authentication和Realtime Database的Firebase项目,生产环境运行正常。现在要集成Cloud Functions,所以搭了Firebase Emulator Suite来测试,避免影响生产资源。模拟器已经初始化,helloWorld模板函数在浏览器里能正常跑。
但用模拟器资源时,数据库调用报错:
FirebaseError: Firebase: Error (auth/network-request-failed).
我在iOS设备上用原生模块测试,没做额外网络配置。
本地Firebase配置文件
firebase.json
{ "functions": [ { "source": "functions", "codebase": "default", "ignore": [ "node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log" ], "predeploy": [ "npm --prefix \"$RESOURCE_DIR\" run lint" ] } ], "emulators": { "auth": { "port": 9099 }, "functions": { "port": 5001 }, "database": { "port": 9000 }, "ui": { "enabled": true }, "singleProjectMode": true } }
functions/index.js
/** * Import function triggers from their respective submodules: * * const {onCall} = require("firebase-functions/v2/https"); * const {onDocumentWritten} = require("firebase-functions/v2/firestore"); * * See a full list of supported triggers at https://firebase.google.com/docs/functions */ const {onRequest} = require("firebase-functions/v2/https"); const logger = require("firebase-functions/logger"); // Create and deploy your first functions // https://firebase.google.com/docs/functions/get-started exports.helloWorld = onRequest((request, response) => { logger.info("Hello logs!", {structuredData: true}); response.send("Hello from Firebase!"); });
React Native 中的 Firebase 配置文件(firebaseConfig.js)
// Import the functions you need from the SDKs you need import { initializeApp } from "firebase/app"; // https://firebase.google.com/docs/web/setup#available-libraries import { getAuth, connectAuthEmulator } from "firebase/auth"; import { getDatabase, connectDatabaseEmulator} from "firebase/database"; // Your web app's Firebase configuration const firebaseConfig = { apiKey: "HIDDEN", authDomain: "HIDDEN", projectId: "HIDDEN", storageBucket: "HIDDEN", messagingSenderId: "HIDDEN", appId: "HIDDEN", databaseURL: "HIDDEN" }; /* Production and Emulator Firebase configs */ // Production: Initialize Firebase App const FIREBASE_APP = initializeApp(firebaseConfig); const FIREBASE_DB = getDatabase(FIREBASE_APP); const FIREBASE_AUTH = getAuth(FIREBASE_APP); connectAuthEmulator(FIREBASE_AUTH, "http://localhost:9099"); connectDatabaseEmulator(FIREBASE_DB, "localhost", 9000); export { FIREBASE_APP, FIREBASE_DB, FIREBASE_AUTH };
我确认端口没问题,但不确定localhost的IP是否正确,已经试过localhost和127.0.0.1。也试过在每个调用FIREBASE_DB或FIREBASE_AUTH的RN文件里调用connectAuthEmulator和connectDatabaseEmulator,还把firebaseConfig里的databaseURL改成和模拟器的URL匹配,但问题还是没解决。
请问怎么正确把React Native应用连接到Firebase Emulator Suite?
1. 替换iOS设备访问的IP地址
iOS设备无法通过localhost或127.0.0.1访问电脑上的模拟器(这两个地址指向设备自身),必须用开发电脑的局域网IP:
- 找到电脑的局域网IP:Mac看「系统设置-网络」,Windows用
ipconfig命令 - 修改
firebaseConfig.js里的模拟器连接地址:// 替换成你的电脑局域网IP,比如192.168.1.100 connectAuthEmulator(FIREBASE_AUTH, "http://192.168.1.100:9099"); connectDatabaseEmulator(FIREBASE_DB, "192.168.1.100", 9000);
2. 让模拟器监听所有网络接口
默认模拟器只绑定localhost,需要修改firebase.json让它允许外部访问:
"emulators": { "auth": { "port": 9099, "host": "0.0.0.0" }, "functions": { "port": 5001, "host": "0.0.0.0" }, "database": { "port": 9000, "host": "0.0.0.0" }, "ui": { "enabled": true }, "singleProjectMode": true }
修改后重启模拟器。
3. 关闭iOS的ATS限制
iOS默认阻止非HTTPS请求,而Firebase模拟器用HTTP,需要在ios/[项目名]/Info.plist里添加例外:
<key>NSAppTransportSecurity</key> <dict> <!-- 宽松模式:允许所有HTTP请求 --> <key>NSAllowsArbitraryLoads</key> <true/> <!-- 严格模式:只允许指定IP的HTTP请求 --> <!-- <key>NSExceptionDomains</key> <dict> <key>192.168.1.100</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> </dict> --> </dict>
4. 确认设备和电脑在同一局域网
开发电脑和iOS测试设备必须连接同一个Wi-Fi,否则设备无法访问模拟器服务。
5. 验证网络连通性
在iOS设备的浏览器里访问:
http://[电脑IP]:9099:能看到Auth模拟器页面说明网络通http://[电脑IP]:9000/.json:能看到数据库初始数据说明模拟器正常
内容的提问来源于stack exchange,提问作者Karl Hernandez

