在SSR getServerSideProps上,Next.js graphql上下文为空{}

在SSR getServerSideProps上,Next.js graphql上下文为空{},next.js,Next.js,我有一个带有getServerSideProps的页面: export const getServerSideProps: GetServerSideProps = async (ctx) => { const apolloClient = initializeApollo() await apolloClient.query({ query: UserQuery, variables: { id: Number(ctx.query.id) }, })

我有一个带有getServerSideProps的页面:

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const apolloClient = initializeApollo()

  await apolloClient.query({
    query: UserQuery,
    variables: { id: Number(ctx.query.id) },
  })

  return {
    props: { initialApolloState: apolloClient.cache.extract() },
  }
}
export const getServerSideProps: GetServerSideProps = async (ctx) => {
  await contextResolver(ctx)
  const apolloClient = initializeApollo(null, ctx)

  await apolloClient.query({
    query: UserQuery,
    variables: { id: Number(ctx.query.id) },
  })

  return {
    props: { initialApolloState: apolloClient.cache.extract() },
  }
}
和用户的解析程序:

resolve: async (_parent, { where }, ctx, info) => {
 const select = new PrismaSelect(info).value

 console.log(ctx) // {} why is empty when i use getServerSideProps?

 const res = await ctx.db.user.findOne({
    where: { id: 1 },
    ...select,
 })

 return null
},
相同的客户端查询工作正常,但由于某种原因,当我使用
getServerSideProps
ctx时,它是空的。如何解决这个问题

我可以将ctx传递给
const apolloClient=initializeAppollo(null,ctx)
,但它不会使用db属性运行apolloServer ctx解析器函数,并且ctx.db将是未定义的


阿波罗服务器:

const apolloServer = new ApolloServer({
  schema,
  async context(ctx: Ctx): Promise<Ctx> {
    ctx.db = prisma

    return ctx
  },
})

export const apolloServerHandler = apolloServer.createHandler({ path: '/api/graphql' })
const阿波罗服务器=新阿波罗服务器({
模式,
异步上下文(ctx:ctx):承诺{
ctx.db=prisma
返回ctx
},
})
export const apolloServerHandler=apolloServer.createHandler({path:'/api/graphql'})
阿波罗客户:

import { useMemo } from 'react'
import { ApolloClient, InMemoryCache, NormalizedCacheObject } from '@apollo/client'
import { IncomingMessage, ServerResponse } from 'http'

type ResolverContext = {
  req?: IncomingMessage
  res?: ServerResponse
}

const typePolicies = {
  Test: {
    keyFields: ['id'],
  },
  User: {
    keyFields: ['id'],
  },
}

let apolloClient: ApolloClient<NormalizedCacheObject>

function createIsomorphLink(context: ResolverContext = {}): any {
  if (typeof window === 'undefined') {
    const { SchemaLink } = require('@apollo/client/link/schema')
    const { schema } = require('backend/graphql/schema')
    return new SchemaLink({ schema, context })
  } else {
    const { HttpLink } = require('@apollo/client/link/http')
    return new HttpLink({
      uri: '/api/graphql',
      credentials: 'same-origin',
    })
  }
}

function createApolloClient(context?: ResolverContext): ApolloClient<NormalizedCacheObject> {
  return new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: createIsomorphLink(context),
    cache: new InMemoryCache({ typePolicies }),
  })
}

export function initializeApollo(
  initialState: any = null,
  // Pages with Next.js data fetching methods, like `getStaticProps`, can send
  // a custom context which will be used by `SchemaLink` to server render pages
  context?: ResolverContext
): ApolloClient<NormalizedCacheObject> {
  const _apolloClient = apolloClient ?? createApolloClient(context)

  // If your page has Next.js data fetching methods that use Apollo Client, the initial state
  // get hydrated here
  if (initialState) {
    // Get existing cache, loaded during client side data fetching
    const existingCache = _apolloClient.extract()
    // Restore the cache using the data passed from getStaticProps/getServerSideProps
    // combined with the existing cached data
    _apolloClient.cache.restore({ ...existingCache, ...initialState })
  }
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === 'undefined') return _apolloClient
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient

  return _apolloClient
}

// eslint-disable-next-line
export function useApollo(initialState: any): ApolloClient<NormalizedCacheObject> {
  const store = useMemo(() => initializeApollo(initialState), [initialState])
  return store
}
从“react”导入{usemo}
从'@apollo/client'导入{apollo客户端,InMemoryCache,NormalizedCacheObject}
从“http”导入{IncomingMessage,ServerResponse}
类型ResolverContext={
请求?:输入消息
res?:服务器响应
}
常量类型策略={
测试:{
关键字字段:['id'],
},
用户:{
关键字字段:['id'],
},
}
让阿波罗客户端:阿波罗客户端
函数createIsomorphLink(上下文:ResolverContext={}):任意{
如果(窗口类型===‘未定义’){
const{SchemaLink}=require(“@apollo/client/link/schema”)
const{schema}=require('backend/graphql/schema')
返回新的SchemaLink({schema,context})
}否则{
const{HttpLink}=require('@apollo/client/link/http')
返回新的HttpLink({
uri:“/api/graphql”,
凭据:“相同来源”,
})
}
}
函数createApolloClient(上下文?:ResolverContext):ApolloClient{
返回新客户端({
ssrMode:typeof window===‘未定义’,
链接:创建同构链接(上下文),
缓存:新的InMemoryCache({TypePolicys}),
})
}
导出函数初始化POLLO(
initialState:any=null,
//带有Next.js数据获取方法的页面,如“getStaticProps”,可以发送
//“SchemaLink”将用于服务器呈现页面的自定义上下文
上下文?:解析上下文
):Apollo客户端{
const_Apollo客户端=Apollo客户端??创建Apollo客户端(上下文)
//如果您的页面具有使用Apollo Client的Next.js数据获取方法,则初始状态为
//在这里补充水分
如果(初始状态){
//获取现有缓存,在客户端数据获取期间加载
const existingCache=\u apolloClient.extract()
//使用从getStaticProps/getServerSideProps传递的数据恢复缓存
//与现有缓存数据相结合
_apolloClient.cache.restore({…existingCache,…initialState})
}
//对于SSG和SSR,始终创建一个新的Apollo客户端
if(typeof window==='undefined')返回
//在客户端中创建一次Apollo客户端
如果(!Apollo客户端)Apollo客户端=\u Apollo客户端
返回(u)
}
//eslint禁用下一行
导出函数useAppollo(初始状态:any):Apollo客户端{
const store=useMemo(()=>InitializeAppollo(initialState),[initialState])
退货商店
}

您需要应用上下文解析器:

async contextResolver(ctx: Ctx): Promise<Ctx> {
    ctx.db = prisma

    return ctx
 },

const apolloServer = new ApolloServer({
  schema,
  context: contextResolver,
})