Firebase App未初始化:Nuxt插件与中间件的适配问题
问题:Nuxt服务端Firebase Admin初始化与中间件调用冲突
我编写了一个名为firebase.server.ts的Nuxt服务端插件,用于初始化Firebase Admin,代码如下:
import { initializeApp, cert, getApp } from "firebase-admin/app"; export default defineNuxtPlugin(() => { const config = useRuntimeConfig(); if (!getApp()) { initializeApp({ credential: cert("./service-account.json"), databaseURL: config.public.databaseURL, }); } });
同时还有一个名为apiauth.ts的认证中间件,用于验证API请求的Auth令牌,代码如下:
import { getAuth } from "firebase-admin/auth"; export default defineEventHandler(async (event: any) => { if (getRequestPath(event).startsWith("/api/")) { // First Check - Check for AUTH token: const authToken = getRequestHeader(event, "authorization")?.split(" ")[1]; if (!authToken) { return { success: false, type: "api", error: "All API requests require a authorization token to be valid.", }; } const auth = getAuth(); // Second Check - Check is a valid AUTH token try { const tokenVerify = await auth.verifyIdToken(authToken); event.authUserConfirm = tokenVerify; } catch (error) { return { success: false, type: "api", error: "Invalid API token, could be expired or incorrect.", }; } } });
原本认为插件会优先完成Firebase实例初始化,中间件可直接调用相关服务,但实际出现错误:The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services.。请问除了在中间件中再次添加初始化代码外,有没有更优的解决方法?
优化解决方案
1. 修正Firebase应用存在性检查逻辑
原插件中!getApp()的判断会在无默认应用时直接抛出异常,导致初始化逻辑无法执行。改用getApps()判断已初始化应用的数量,避免异常阻断流程:
// 修改后的firebase.server.ts import { initializeApp, cert, getApps } from "firebase-admin/app"; export default defineNuxtPlugin(() => { const config = useRuntimeConfig(); // 仅当无已初始化应用时才执行初始化 if (getApps().length === 0) { initializeApp({ credential: cert("./service-account.json"), databaseURL: config.public.databaseURL, }); } });
2. 提升插件执行优先级
在nuxt.config.ts中显式设置插件的最高优先级,确保它在所有中间件之前执行:
export default defineNuxtConfig({ plugins: [ { src: '~/plugins/firebase.server.ts', mode: 'server', priority: 1000 // 数值越高,执行时机越早 } ] })
3. 将Firebase服务注入Nuxt上下文(推荐)
在插件中初始化并注入Firebase Auth服务到Nuxt上下文,中间件直接从上下文获取实例,彻底避免初始化顺序和重复调用问题:
// 修改后的firebase.server.ts import { initializeApp, cert, getApps, getApp } from "firebase-admin/app"; import { getAuth } from "firebase-admin/auth"; export default defineNuxtPlugin(() => { const config = useRuntimeConfig(); if (getApps().length === 0) { initializeApp({ credential: cert("./service-account.json"), databaseURL: config.public.databaseURL, }); } // 获取已初始化的Auth服务并注入上下文 const firebaseAuth = getAuth(getApp()); return { provide: { firebaseAuth } }; });
// 修改后的apiauth.ts export default defineEventHandler(async (event: any) => { if (getRequestPath(event).startsWith("/api/")) { const authToken = getRequestHeader(event, "authorization")?.split(" ")[1]; if (!authToken) { return { success: false, type: "api", error: "All API requests require a authorization token to be valid.", }; } // 从Nuxt上下文获取已初始化的Auth服务 const { firebaseAuth } = useNuxtApp(event); try { const tokenVerify = await firebaseAuth.verifyIdToken(authToken); event.authUserConfirm = tokenVerify; } catch (error) { return { success: false, type: "api", error: "Invalid API token, could be expired or incorrect.", }; } } });
内容的提问来源于stack exchange,提问作者Joshua
相关产品推荐
相关产品推荐

