在下一个JS中:
-
SSR https://nextjs.org/docs/basic-features/pages#server-side-rendering- 服务端渲染 -
getServerSideProps
-
SSG https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation- 生成静态站点 -
getStaticPaths
& getStaticProps
- CSR - 客户端渲染 - 其他一切
值得注意的是,SSG 功能是在服务器端运行的。
在客户端上,您只想创建 Apollo Client 的单个全局实例。创建 Apollo Client 的多个实例将使保持与客户端同步变得困难。这个困难是因为 Apollo Cache、Apollo Link 等都将存储在 Apollo Client 的不同实例中。
接下来,常见的是将Apollo Client的全局实例放在页面上_app.js
并使用阿波罗提供商 https://www.apollographql.com/docs/react/api/react/hooks/#example。在其他客户端页面上,您可以使用useQuery https://www.apollographql.com/docs/react/api/react/hooks/#example-2调用您的单个全局实例的钩子。
服务器端(SSR)功能getStaticProps
or getServerSideProps
无权访问 Apollo 的客户端实例、Next 的客户端实例或其他服务器端功能。因此,您必须在每个使用的页面上定义 Apollo 连接getStaticPaths
, getStaticProps
, or getServerSideProps
并且需要访问 Apollo 客户端,否则服务器端调用将无法使用它。
自从第一次钩子规则 https://reactjs.org/docs/hooks-rules.html是它们只能在顶层(客户端)调用,不能在服务器端函数中使用它们。不,你不能跑useQuery
在下一个 SSR 或 SSG 功能中。
您提供的示例是保持缓存同步,并且是定义客户的方式已经过时 https://www.apollographql.com/docs/react/performance/server-side-rendering/#rehydrating-the-client-side-cache。这是一个更符合官方文档的简化示例。
graphqlClient.js
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client';
// Used server and client side - can't use react hooks
export const graphqlClient = new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: 'YOUR_GQL_ENDPOINT',
}),
ssrMode: typeof window === 'undefined',
});
_app.js - 所有客户端页面都使用的单个实例,因为它包装了整个应用程序
import graphqlClient from 'my/path/graphqlClient';
const App = ({ Component, pageProps }) => {
const client = graphqlClient();
return (
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
);
};
每个客户端页面/组件都可以使用 useQuery 钩子,因为 Apollo 客户端将应用程序包装在_app.js
客户端查询
import { gql, useQuery } from '@apollo/client';
const About = () => {
const { data } = useQuery(YOUR_QUERY); // uses your single instance defined in _app.js
return (
...
)
}
每个使用SSR或SSG功能并需要访问Apollo的页面都必须实例化一个新的Apollo实例。
SSG
import graphqlClient from 'my/path/graphqlClient';
//does not have access to _app.js or client and must define new Apollo Client instance
export const getStaticProps = async () => {
const client = graphqlClient();//
const { data } = await client.query({query: YOUR_QUERY});
};
export const getStaticPaths = async () => {
const client = graphqlClient();
const { data } = await client.query({query: YOUR_QUERY});
};
SSR
import graphqlClient from 'my/path/graphqlClient';
//does not have access to _app.js or client and must define new Apollo Client instance
export const getServerSideProps = async () => {
const client = graphqlClient();
const { data } = await client.query({query: YOUR_QUERY});
};
最后,为了简化你可以使用的东西graphql 代码生成器 https://www.graphql-code-generator.com/自动生成 Apollo 查询、变异等钩子(以及 TS 用户的类型)以及服务器端兼容Next.js 的查询和变异函数 https://www.graphql-code-generator.com/docs/plugins/typescript-apollo-next.