Next.js 12.0.10中getServerSideProps调用Firebase 9.6.6的getStories函数时触发「初始化前无法访问getStories」错误
Hey there, let's break down why you're hitting this error and how to fix it.
The Cannot access 'getStories' before initialization error typically pops up when a module tries to use an exported value before the module that exports it has finished initializing. In your case, the issue ties to top-level module execution order in Next.js's SSR environment.
Looking at your storyService.js, you're creating storiesRef at the module's top level right when it's imported. Even though your Firebase initialization looks synchronous, Next.js's server-side rendering pipeline can have edge cases where the database export from firebase.js isn't fully ready before storyService.js tries to use it to create the collection reference.
Solution 1: Move collection reference creation inside service functions
Instead of defining storiesRef at the module level, create it inside each service function that needs it. This ensures you only access the database export after both modules have fully initialized.
Here's the updated lib/services/storyService.js:
import { collection, query, getDocs, getDoc, setDoc, doc, serverTimestamp, orderBy, } from 'firebase/firestore'; import { database } from '../firebase/firebase'; import slugify from 'slugify'; import { random } from 'lodash'; export const createStory = async (payload) => { // Create the collection reference inside the function const storiesRef = collection(database, 'stories'); const slugTitle = slugify(payload.title); const slug = slugTitle + '-' + random(0, 100000); const updatedPayload = { ...payload, slug, type: 'published', createdAt: serverTimestamp(), }; return setDoc(doc(storiesRef, slug), updatedPayload); }; export const getStories = async () => { // Create the collection reference inside the function const storiesRef = collection(database, 'stories'); const q = query(storiesRef, orderBy('createdAt', 'desc')); return getDocs(q); }; export const getStoryBySlug = async (slug) => { const docRef = doc(database, 'stories', slug); return getDoc(docRef); };
Solution 2: Add Firebase app initialization guard (Next.js SSR best practice)
To avoid potential issues with multiple Firebase app initializations on the server (which can cause unexpected state inconsistencies), update your lib/firebase/firebase.js to check if an app already exists before initializing:
import { initializeApp, getApps, getApp } from 'firebase/app'; import { getAnalytics } from 'firebase/analytics'; import { getFirestore } from 'firebase/firestore'; import { getAuth } from 'firebase/auth'; const firebaseConfig = { apiKey: 'XXX', authDomain: 'XXX', projectId: 'XXX', storageBucket: 'X', messagingSenderId: 'XXX', appId: 'XXX', measurementId: 'XXX', }; // Only initialize Firebase if no app exists already const app = !getApps().length ? initializeApp(firebaseConfig) : getApp(); // Initialize Analytics only on the client side (it doesn't work in SSR) let analytics; if (typeof window !== 'undefined') { analytics = getAnalytics(app); } export const database = getFirestore(app); export const auth = getAuth(app);
Why this works
- By moving
storiesRefcreation inside your functions, you delay accessing thedatabaseexport until the function is actually called (ingetServerSideProps), ensuring both modules have finished initializing. - The Firebase app guard prevents redundant initializations on the server, which can lead to module state inconsistencies. The Analytics check avoids another error since Firebase Analytics isn't supported in server-side environments.
Try these changes, and your getStories call in getServerSideProps should work as expected!
内容的提问来源于stack exchange,提问作者Kevin Yobeth

