如何从 NextJS 服务器为 Apollo 客户端补充水分

Posted

技术标签:

【中文标题】如何从 NextJS 服务器为 Apollo 客户端补充水分【英文标题】:How to hydrate Apollo client from NextJS server 【发布时间】:2019-09-15 23:34:39 【问题描述】:

我正在使用带有 Apollo 客户端的自定义 NextJS 服务器。我想在服务器端获取 GraphQL 数据,然后将其发送到客户端。我有点能够做到这一点,但客户端再次获取它。我了解 Apollo 缓存仅在服务器上可用,然后需要发送到客户端并从那里恢复。

Apollo docs 提到了 s-s-r,但我不想使用 Apollo 客户端完全渲染我的应用程序,我想使用 NextJS,我只想从 Apollo 客户端获取数据并手动将其注入 html 以在客户端恢复它。我查看了一些使用 Apollo 的 NextJS 示例,但没有一个显示如何做到这一点。

这是我的自定义请求处理程序:

const app = next( dev: process.env.NODE_ENV !== 'production' );

const customHandler = async (req, res) => 
  const rendered = await app.renderToHTML(req, res, req.path, req.query);
  // somehow get the data from the apollo cache and inject it in the rendered html
  res.send(rendered);

【问题讨论】:

【参考方案1】:

当您在服务器中创建ApolloClient 时,您可以传递initialState 来水合缓存。

const createApolloClient = ( initialState, headers ) =>
    new ApolloClient(
      uri: GRAPHQL_URL,
      cache: new InMemoryCache().restore(initialState || ) // hydrate cache
    );

export default withApollo(PageComponent,  s-s-r = true  = ) => 

  const WithApollo = ( apolloClient, apolloState, ...pageProps ) => 
    const client = apolloClient || createApolloClient( initialState: apolloState, headers:  );

     ... rest of your code. 
  );
);

我为此创建了一个名为nextjs-with-apollo 的包。看看https://github.com/adikari/nextjs-with-apollo。一旦你安装了这个包,就创建一个 HOC。

// hocs/withApollo.js
import withApollo from 'nextjs-with-apollo';
import ApolloClient from 'apollo-client';
import  InMemoryCache  from 'apollo-cache-inmemory';

const GRAPHQL_URL = 'https://your-graphql-url';

const createApolloClient = ( initialState, headers ) =>
    new ApolloClient(
      uri: GRAPHQL_URL,
      cache: new InMemoryCache().restore(initialState || ) // hydrate cache
    );

export default withApollo(createApolloClient);

然后您可以将 hoc 用于您的 next 页面。

import React from 'react';
import  useQuery  from '@apollo/react-hooks';

import withApollo from 'hocs/withApollo';

const QUERY = gql`
  query Profile 
    profile 
      name
      displayname
    
  
`;

const ProfilePage = () => 
  const  loading, error, data  = useQuery(PROFILE_QUERY);

  if (loading) 
    return <p>loading..</p>;
  

  if (error) 
    return JSON.stringify(error);
  

  return (
    <>
      <p>user name: data.profile.displayname</p>
      <p>name: data.profile.name</p>
    </>
  );
;

export default withApollo(ProfilePage);

【讨论】:

以上是关于如何从 NextJS 服务器为 Apollo 客户端补充水分的主要内容,如果未能解决你的问题,请参考以下文章

使用 Apollo 客户端在 nextJs 中传递授权标头的最佳方法? ReferenceError: localStorage 未定义

如果你有 apollo react 钩子从后端获取数据,你如何使用 nextjs 进行服务器端渲染?

作为道具传递与提取缓存 Apollo 客户端 Nextjs

在 nextJS 上配置 apollo 客户端以进行订阅的问题

无法使用 apollo-server-micro 和 NextJS 上传 1MB 以上的文件

Apollo 客户端未在 Nextjs Lamda 中发送 JWT 不记名令牌