Strapi+Next.js App Router中SSR组件使用GraphQL+Apollo请求的问题
解决服务器组件中Apollo查询报错的方案
错误原因
你当前的Apollo Client实例是在标记了"use client"的文件中创建的,属于客户端专属API,无法在服务器组件(App Router中的默认组件)中直接调用client.query(),因此触发报错。
方案一:直接用Fetch发送GraphQL请求(无需Apollo)
服务器组件本身支持async/await,可以直接通过原生Fetch向Strapi的GraphQL接口发送请求,这是最简单的无依赖方案:
修改app/page.tsx:
import { RootFooter, RootMain } from "@/compoents/organisms"; export default async function Home() { const STRAPI_URL = process.env.STRAPI_URL || "http://localhost:1337"; const res = await fetch(`${STRAPI_URL}/graphql`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: ` { todos(sort: "id:desc") { data { id attributes { todoText createdAt } } } } ` }), // 根据需求设置缓存策略,Next.js支持多种缓存选项 cache: "force-cache" }); if (!res.ok) throw new Error("请求数据失败"); const { data } = await res.json(); console.log(data, "data"); return ( <> <RootMain> <h1 className="text-white">{data.todos.data[0]?.attributes.todoText || "暂无数据"}</h1> </RootMain> <RootFooter /> </> ); }
方案二:创建服务器端专属Apollo Client实例
如果仍想使用Apollo的查询能力,需要在非客户端文件中创建服务器端的Apollo Client(禁用客户端特性):
- 创建
lib/apollo-server.ts(不要加"use client"):
import { InMemoryCache, ApolloClient } from "@apollo/client"; const STRAPI_URL = process.env.STRAPI_URL || "http://localhost:1337"; export function createServerApolloClient() { return new ApolloClient({ uri: `${STRAPI_URL}/graphql`, cache: new InMemoryCache(), ssrMode: true, // 开启SSR模式,禁用客户端渲染相关逻辑 }); }
- 修改
app/page.tsx:
import { RootFooter, RootMain } from "@/compoents/organisms"; import { GETQUERY } from "@/query/schema"; import { createServerApolloClient } from "@/lib/apollo-server"; export default async function Home() { // 每次请求创建新的客户端实例,避免缓存污染 const client = createServerApolloClient(); const { data } = await client.query({ query: GETQUERY }); console.log(data, "data"); return ( <> <RootMain> <h1 className="text-white">{data.todos.data[0]?.attributes.todoText || "暂无数据"}</h1> </RootMain> <RootFooter /> </> ); }
替代方案:使用轻量GraphQL请求库
如果觉得Apollo过于厚重,可以选择更适合服务器端的轻量库,比如graphql-request:
- 安装依赖:
npm install graphql-request graphql
- 修改
app/page.tsx:
import { RootFooter, RootMain } from "@/compoents/organisms"; import { request, gql } from "graphql-request"; const STRAPI_GQL_URL = process.env.STRAPI_URL || "http://localhost:1337/graphql"; export default async function Home() { const query = gql` { todos(sort: "id:desc") { data { id attributes { todoText createdAt } } } } `; const data = await request(STRAPI_GQL_URL, query); console.log(data, "data"); return ( <> <RootMain> <h1 className="text-white">{data.todos.data[0]?.attributes.todoText || "暂无数据"}</h1> </RootMain> <RootFooter /> </> ); }
内容的提问来源于stack exchange,提问作者Zahar
相关产品推荐
相关产品推荐

