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

Next.js13部署Vercel出现客户端异常的原因及解决方法

问题原因与解决方案

核心原因

  1. Supabase客户端跨环境复用问题:SSR过程中,服务端创建的Supabase实例被意外传递到客户端,服务端渲染完成后连接被关闭,客户端后续异步操作尝试使用已关闭的连接,触发错误。
  2. React-Query SSR数据hydration不完整:服务端预取数据时,异步查询未完全完成就返回页面,导致客户端接收的缓存数据不匹配,后续异步响应时消息通道已关闭。
  3. 实时订阅误用:在服务端组件中初始化Supabase实时订阅,服务端渲染结束后订阅连接被销毁,客户端接管时触发连接关闭错误。

解决步骤

1. 严格分离Supabase服务端/客户端实例

确保服务端和客户端使用各自的Supabase初始化方法,避免跨环境复用实例:

  • 服务端组件(App Router):使用createServerComponentClient,依赖next/headers的cookies:
    import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
    import { cookies } from 'next/headers';
    
    export default async function SSRPage() {
      const supabase = createServerComponentClient({ cookies });
      // 等待查询完成后再渲染
      const { data } = await supabase.from('your_table').select('*');
      return <div>{JSON.stringify(data)}</div>;
    }
    
  • 客户端组件:使用createClientComponentClient,无需传递cookies:
    import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
    
    export default function ClientPage() {
      const supabase = createClientComponentClient();
      // 客户端侧的数据操作
      return <div>Client Content</div>;
    }
    

2. 确保React-Query SSR数据正确传递

使用dehydrate和Hydrate组件完成服务端数据预取与客户端缓存同步,避免异步操作未完成就结束渲染:

import { dehydrate, QueryClient } from '@tanstack/react-query';
import { Hydrate } from '@tanstack/react-query-nextjs';
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import ClientComponent from './ClientComponent';

export default async function SSRPage() {
  const queryClient = new QueryClient();
  // 等待查询完成,确保数据被预取
  await queryClient.fetchQuery({
    queryKey: ['your_data'],
    queryFn: async () => {
      const supabase = createServerComponentClient({ cookies });
      const { data } = await supabase.from('your_table').select('*');
      return data;
    },
  });

  return (
    <Hydrate state={dehydrate(queryClient)}>
      <ClientComponent />
    </Hydrate>
  );
}

注意:客户端组件中使用useQuery时,queryKey要与服务端预取的一致,确保直接复用缓存数据。

3. 避免在服务端组件中使用实时订阅

Supabase实时订阅属于客户端特性,必须放在客户端组件的生命周期钩子中初始化:

// 客户端组件中使用实时订阅
import { useEffect } from 'react';
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';

export default function ClientComponent() {
  const supabase = createClientComponentClient();

  useEffect(() => {
    const channel = supabase.channel('your_table')
      .on('INSERT', (payload) => {
        console.log('New record:', payload.new);
      })
      .subscribe();

    // 组件卸载时取消订阅
    return () => {
      supabase.removeChannel(channel);
    };
  }, [supabase]);

  return <div>Real-time Content</div>;
}

4. 检查Vercel部署配置

  • 若使用Edge Runtime,确保@supabase/auth-helpers-nextjs版本适配(v0.7.0+支持Edge环境);
  • 在Vercel控制台调整Serverless函数超时时间(默认10秒,可延长至60秒),避免服务端查询未完成就被终止;
  • 查看Vercel函数日志,确认是否有服务端报错导致连接提前关闭。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:43:53