You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js集成Firestore时顶层await报错,如何解决?

解决Next.js Pages Router中Firestore查询的顶层await错误

问题原因

你在组件外部使用顶层await,即使配置了experiments.topLevelAwait: true,Next.js 13.2.1的Pages Router仍可能因为客户端环境兼容性或框架设计限制,导致该配置不生效。此外,组件外部的顶层await会阻塞组件加载,并非最佳实践。

推荐解决方案

方案1:使用getServerSideProps(服务端渲染,实时数据)

在Pages Router中,getServerSideProps是服务端执行的函数,可安全使用await获取数据,再将数据传递给组件,适合需要实时更新的数据场景。

// pages/profilePage.js
import { getDocs, collection } from "firebase/firestore";
import { db } from "../path-to-your-firebase-config";

export default function ProfilePage({ cities }) {
  return (
    <div>
      <h1>城市列表</h1>
      <ul>
        {cities.map(city => (
          <li key={city.id}>{city.name}</li>
        ))}
      </ul>
    </div>
  );
}

// 服务端执行的数据获取函数
export async function getServerSideProps() {
  const querySnapshot = await getDocs(collection(db, "cities"));
  const cities = querySnapshot.docs.map(doc => ({
    id: doc.id,
    ...doc.data()
  }));

  return {
    props: { cities } // 将数据传递给组件
  };
}

方案2:使用getStaticProps(静态生成,非实时数据)

如果数据更新频率低,可使用getStaticProps在构建时获取数据,生成静态页面,性能更优。还可通过revalidate配置增量静态再生,定期更新页面。

// pages/profilePage.js
import { getDocs, collection } from "firebase/firestore";
import { db } from "../path-to-your-firebase-config";

export default function ProfilePage({ cities }) {
  return (
    <div>
      <h1>城市列表</h1>
      <ul>
        {cities.map(city => (
          <li key={city.id}>{city.name}</li>
        ))}
      </ul>
    </div>
  );
}

// 构建时执行的数据获取函数
export async function getStaticProps() {
  const querySnapshot = await getDocs(collection(db, "cities"));
  const cities = querySnapshot.docs.map(doc => ({
    id: doc.id,
    ...doc.data()
  }));

  return {
    props: { cities },
    revalidate: 60 // 每60秒重新生成页面(可选)
  };
}

方案3:客户端组件内使用useEffect(客户端数据获取)

如果需要在客户端交互后获取数据,可通过useEffect钩子配合async函数执行查询,避免顶层await的问题。

// pages/profilePage.js
import { useState, useEffect } from "react";
import { getDocs, collection } from "firebase/firestore";
import { db } from "../path-to-your-firebase-config";

export default function ProfilePage() {
  const [cities, setCities] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchCities = async () => {
      try {
        const querySnapshot = await getDocs(collection(db, "cities"));
        const citiesData = querySnapshot.docs.map(doc => ({
          id: doc.id,
          ...doc.data()
        }));
        setCities(citiesData);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchCities();
  }, []); // 空依赖数组,仅组件挂载时执行一次

  if (loading) return <div>加载中...</div>;
  if (error) return <div>出错了:{error}</div>;

  return (
    <div>
      <h1>城市列表</h1>
      <ul>
        {cities.map(city => (
          <li key={city.id}>{city.name}</li>
        ))}
      </ul>
    </div>
  );
}

额外注意事项

  • 确保next.config.js的配置格式正确,示例如下:
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  experiments: {
    topLevelAwait: true
  }
};

module.exports = nextConfig;
  • 优先使用Next.js官方推荐的数据获取方法(getServerSideProps/getStaticProps),这更符合框架设计,也能避免客户端兼容性问题。

内容的提问来源于stack exchange,提问作者Clément Ramos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 18:47:12