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

求助:Next.js 13+Supabase实现SSG失败,始终触发SSR

Next.js 13 + Supabase 静态站点生成(SSG)问题排查与解决

你当前的核心问题是混淆了Next.js 13 App Router与Pages Router的静态生成机制,同时部分请求配置存在疏漏,导致页面始终以SSR方式渲染。以下是对尝试方法的问题分析及正确实现方案:


已尝试方法的问题点

  1. 方法1:通过API路由中转请求

    • 页面组件中请求本地API时,未显式配置缓存策略,默认会被视为动态请求触发SSR
    • 无需额外通过API路由中转,直接在页面组件请求Supabase更高效
  2. 方法2:带force-cache的fetch请求

    • Supabase REST API默认响应头可能包含Cache-Control: no-cache,会覆盖你的fetch缓存配置
    • 未明确设置缓存有效期,无法确保构建时预渲染数据
  3. 方法3:使用getStaticProps

    • getStaticProps是Pages Router专属API,在App Router(app目录)中完全不生效

正确实现方案(App Router)

方案1:直接配置可缓存的Supabase REST请求

在页面组件中直接请求Supabase,强制缓存并覆盖默认缓存头:

// app/composers/page.tsx
type Composer = {
  id: number;
  name: string;
  // 补充你的字段定义
};

async function getComposers() {
  const res = await fetch(
    `${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/composers?select=*&order=id.asc`,
    {
      cache: "force-cache", // 构建时预拉取数据并缓存
      next: { revalidate: 86400 }, // 可选:设置每日重新验证,实现增量静态再生(ISR)
      headers: {
        "Apikey": process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
        "Cache-Control": "s-maxage=86400, stale-while-revalidate" // 覆盖Supabase默认缓存头
      } as HeadersInit,
    }
  );

  if (!res.ok) throw new Error('获取作曲家数据失败');
  const data: Composer[] = await res.json();
  return data;
}

export default async function ComposersPage() {
  const composers = await getComposers();

  return (
    <div>
      <h1>作曲家列表</h1>
      <ul>
        {composers.map(composer => (
          <li key={composer.id}>{composer.name}</li>
        ))}
      </ul>
    </div>
  );
}

方案2:使用Supabase客户端并配置缓存

如果使用Supabase JS客户端,需手动设置缓存头确保静态生成:

// app/composers/page.tsx
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';

type Composer = {
  id: number;
  name: string;
};

async function getComposers() {
  const supabase = createClientComponentClient();
  const { data, error } = await supabase
    .from('composers')
    .select('*')
    .order('id', { ascending: true })
    .setHeader('Cache-Control', 's-maxage=86400, stale-while-revalidate');

  if (error) throw error;
  return data as Composer[];
}

// 注意:页面中不要使用cookies()、headers()等动态函数,否则会触发SSR
export default async function ComposersPage() {
  const composers = await getComposers();

  return (
    <div>
      <h1>作曲家列表</h1>
      <ul>
        {composers.map(composer => (
          <li key={composer.id}>{composer.name}</li>
        ))}
      </ul>
    </div>
  );
}

验证静态生成是否生效

  1. 执行npm run build,构建完成后查看.next/static/app/composers目录,若生成page.html文件则说明静态生成成功
  2. 启动生产服务npm run start,查看页面响应头,若包含x-nextjs-cache: HIT则表示页面从静态缓存读取

关键注意事项

  • App Router默认静态渲染,无需getStaticProps,只要数据请求可缓存且无动态依赖(如用户会话、请求头)
  • 必须覆盖Supabase默认的禁止缓存响应头,否则无法实现静态预渲染
  • 若页面使用cookies()、headers()等动态API,会自动触发SSR,无法静态生成

内容的提问来源于stack exchange,提问作者vlovin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:52:53