如何解决SvelteKit项目中Firebase初始化报window is not defined错误
解决SvelteKit中Firebase "window is not defined" 错误的两种方案
错误原因
SvelteKit默认启用服务端渲染(SSR),组件顶层代码会在服务端执行,但服务端环境不存在window对象。Firebase的部分模块(如Analytics)初始化时依赖window,直接在组件顶层执行初始化代码就会触发该错误。
方案一:无需onMount的条件初始化
通过判断浏览器环境延迟初始化Firebase,避开服务端执行阶段。同时将依赖window的Analytics模块单独处理,避免在服务端加载。
修改后的组件代码:
<script> import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; import { collection, addDoc } from "firebase/firestore"; // 延迟导入依赖window的模块 let getAnalytics; let song = 'song'; let app, db; const firebaseConfig = { // 你的Firebase配置 }; // 仅在浏览器环境初始化 if (typeof window !== 'undefined') { // 动态导入Analytics import('firebase/analytics').then(module => { getAnalytics = module.getAnalytics; }); app = initializeApp(firebaseConfig); db = getFirestore(app); // 可选:初始化Analytics(仅浏览器) if (getAnalytics) getAnalytics(app); } async function sendSong() { // 确保db已初始化再调用 if (!db) return; try { const docRef = await addDoc(collection(db, "songs"), { title: song, // 修正原代码的对象包裹错误 artist: "test" // 修正拼写错误 }); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); } } </script> <input bind:value={song}> <button on:click={sendSong}>提交歌曲</button> <style> </style>
方案二:onMount初始化+全局Store共享(支持外部调用)
如果必须用onMount初始化,可以将Firebase实例存入Svelte Store,让组件内外都能访问。
步骤1:创建Firebase Store文件(src/lib/firebase.js)
import { writable } from 'svelte/store'; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; import { getAnalytics } from "firebase/analytics"; const firebaseConfig = { // 你的Firebase配置 }; export const firebaseStore = writable(null); export function initFirebase() { const app = initializeApp(firebaseConfig); const db = getFirestore(app); const analytics = getAnalytics(app); firebaseStore.set({ app, db, analytics }); }
步骤2:在组件中使用
<script> import { onMount } from 'svelte'; import { firebaseStore } from '$lib/firebase'; import { collection, addDoc } from "firebase/firestore"; let song = 'song'; let db; // 订阅store获取db实例 const unsubscribe = firebaseStore.subscribe(value => { if (value) db = value.db; }); onMount(() => { import('$lib/firebase').then(module => { module.initFirebase(); }); return unsubscribe; }); async function sendSong() { if (!db) return; try { const docRef = await addDoc(collection(db, "songs"), { title: song, artist: "test" }); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); } } </script> <input bind:value={song}> <button on:click={sendSong}>提交歌曲</button> <style> </style>
这种方式下,其他组件或模块只要导入firebaseStore就能获取已初始化的Firebase实例,实现跨组件共享。
内容的提问来源于stack exchange,提问作者pohadkove
相关产品推荐
相关产品推荐

