在NextJS应用中如何从Apollo Link Context获取Express HTTP请求?
在Next.js中为Apollo Client服务端渲染获取Express Request对象
我来帮你解决这个问题——在Next.js的SSR场景下,要把Express的Request对象传递给Apollo Client的初始化函数,核心就是把req从服务端的上下文里传进去,具体步骤如下:
第一步:修改createApolloClient函数,接收req参数
首先要让你的createApolloClient支持接收req参数,这样服务端渲染时就能把Request对象传进来了:
function createApolloClient(initialState = {}, req = null) { const httpLink = new HttpLink({ uri: `${baseUrl}/graphql`, credentials: 'same-origin', fetch }) const authLink = setContext((_, prevCtx) => { let token = '' if (typeof window === 'undefined') // 现在可以使用传入的req参数提取服务端Cookie了 token = getCookieFromServer(authCookieName, req) else token = getCookieFromBrowser(authCookieName) return ({ headers: { 'Auth-Token': token } }) }) const client = new ApolloClient({ ssrMode: typeof window === 'undefined', cache: new InMemoryCache().restore(initialState), link: authLink.concat(httpLink) }) return client }
第二步:在服务端上下文里传递req
根据你使用的Next.js页面路由类型,有两种常见的传递方式:
1. 在getServerSideProps中传递req
如果你的页面使用getServerSideProps做服务端渲染,直接从上下文参数里拿到req并传给createApolloClient:
export async function getServerSideProps(context) { // 把context.req传入初始化函数 const apolloClient = createApolloClient({}, context.req); // 这里可以执行你的GraphQL查询,比如: // await apolloClient.query({ query: YOUR_QUERY }); return { props: { initialApolloState: apolloClient.cache.extract(), }, }; }
2. 在_app.js的getInitialProps中传递req
如果你的全局_app.js中统一处理Apollo Client的初始化,可以在getInitialProps里从ctx拿到req:
function MyApp({ Component, pageProps, apolloClient }) { return ( <ApolloProvider client={apolloClient}> <Component {...pageProps} /> </ApolloProvider> ); } MyApp.getInitialProps = async ({ Component, ctx }) => { // 传入ctx.req初始化Apollo Client const apolloClient = createApolloClient({}, ctx.req); let pageProps = {}; if (Component.getInitialProps) { pageProps = await Component.getInitialProps(ctx); } return { pageProps, apolloClient, initialApolloState: apolloClient.cache.extract(), }; }; export default MyApp;
针对Next.js 13+ App Router的补充
如果你的项目用的是App Router(Server Components),不需要依赖Express的req对象,可以直接用Next.js提供的headers()函数获取Cookie:
// 定义服务端获取Cookie的函数 function getCookieFromServer(name) { const cookieHeader = headers().get('cookie'); if (!cookieHeader) return ''; // 解析Cookie字符串为键值对 const cookies = cookieHeader.split(';').reduce((acc, cookie) => { const [key, value] = cookie.trim().split('='); acc[key] = value; return acc; }, {}); return cookies[name] || ''; } // 修改createApolloClient,不再需要req参数 function createApolloClient(initialState = {}) { const httpLink = new HttpLink({ uri: `${baseUrl}/graphql`, credentials: 'same-origin', fetch }) const authLink = setContext((_, prevCtx) => { let token = '' if (typeof window === 'undefined') token = getCookieFromServer(authCookieName) else token = getCookieFromBrowser(authCookieName) return ({ headers: { 'Auth-Token': token } }) }) const client = new ApolloClient({ ssrMode: typeof window === 'undefined', cache: new InMemoryCache().restore(initialState), link: authLink.concat(httpLink) }) return client }
这样在Server Components中初始化Apollo Client时,就能直接获取到服务端的Cookie了。
内容的提问来源于stack exchange,提问作者acmoune
相关产品推荐
相关产品推荐

