Next.js集成Google Firebase认证时应用崩溃问题求助
解决Next.js中Firebase Google认证崩溃问题
问题根源分析
报错dependent-sdk-initialized-before-auth说明其他Firebase SDK在Auth完成初始化前就尝试调用Auth功能,同时代码存在几处直接触发崩溃的问题:
logoutFirebase函数中signOut未导入,会直接抛出未定义错误- 直接通过
auth.currentUser判断登录状态,在Next.js的服务端渲染/静态生成环境下不可靠,且无法实时监听状态变化 - 未处理Firebase在Next.js中的重复初始化问题(热重载或多页面导入可能触发)
分步修复方案
1. 修正firebase-config.js配置
import { initializeApp, getApps, getApp } from 'firebase/app'; import { initializeAuth, browserLocalPersistence, browserPopupRedirectResolver, indexedDBLocalPersistence, signInWithRedirect, GoogleAuthProvider, signOut, onAuthStateChanged } from "firebase/auth"; const firebaseCredentials = { apiKey: process.env.FIREBASE_API_KEY, authDomain: process.env.AUTH_DOMAIN, projectId: process.env.PROJECT_ID, storageBucket: process.env.STORAGE_BUCKET, messagingSenderId: process.env.MESSAGING_SENDER_ID, appId: process.env.APP_ID }; // 单例模式避免重复初始化 let app; let auth; if (!getApps().length) { app = initializeApp(firebaseCredentials); // 优先初始化Auth,确保其他Firebase服务在Auth之后初始化 auth = initializeAuth(app, { persistence: [indexedDBLocalPersistence, browserLocalPersistence], }); } else { app = getApp(); auth = getAuth(app); } // 替换同步获取用户的方法,改为提供状态监听函数 export const listenToAuthState = (callback) => { return onAuthStateChanged(auth, callback); }; export const loginFirebase = () => { signInWithRedirect(auth, new GoogleAuthProvider(), browserPopupRedirectResolver); }; export const logoutFirebase = () => { signOut(auth); };
2. 重构Auth组件,正确监听登录状态
'use client' // Next.js 13+版本需添加,确保组件在客户端运行 import { useRouter } from 'next/router'; import { useState, useEffect } from 'react'; import { IconButton, Menu, MenuItem, Button, Box } from '@mui/material'; import { AccountCircle, Logout, ManageAccounts, RateReview, Google } from '@mui/icons-material'; import { listenToAuthState, loginFirebase, logoutFirebase } from '../firebase-config'; export const Auth = () => { const router = useRouter(); const [anchorEl, setAnchorEl] = useState(null); const [user, setUser] = useState(null); useEffect(() => { // 监听Auth状态变化,实时更新用户信息 const unsubscribe = listenToAuthState((currentUser) => { setUser(currentUser); }); // 组件卸载时取消监听 return () => unsubscribe(); }, []); const handleMenu = (event) => setAnchorEl(event.currentTarget); const handleClose = () => setAnchorEl(null); const redirectFromMenu = (url) => { handleClose(); router.push(url); }; return ( <Box sx={{ marginLeft: 'auto' }}> {user ? ( <> <IconButton size="large" aria-label="account of current user" aria-controls="menu-appbar" aria-haspopup="true" onClick={handleMenu} color="inherit" > <AccountCircle /> </IconButton> <Menu id="menu-appbar" anchorEl={anchorEl} anchorOrigin={{ vertical: 'top', horizontal: 'right', }} keepMounted transformOrigin={{ vertical: 'top', horizontal: 'right', }} open={Boolean(anchorEl)} onClose={handleClose} > <MenuItem onClick={() => redirectFromMenu('/account')}><ManageAccounts /> My Account</MenuItem> <MenuItem onClick={() => redirectFromMenu('/reviews/write')}><RateReview /> Write Review</MenuItem> <MenuItem onClick={logoutFirebase}><Logout /> Logout</MenuItem> </Menu> </> ) : ( <Button size='small' onClick={loginFirebase} startIcon={<Google />} variant='contained' color='secondary'> Login with Google </Button> )} </Box> ); };
3. 额外注意事项
- 确保所有其他Firebase服务(如Firestore、Storage)的初始化代码都在Auth初始化之后执行
- 检查
.env.local文件,确认所有Firebase环境变量都已正确配置,且变量名与代码中的一致 - 若使用Next.js 13+ App Router,需确保Auth组件为客户端组件(添加
'use client'指令)
内容的提问来源于stack exchange,提问作者J. Whitehead
相关产品推荐
相关产品推荐

