I posted this in the apollo-client repo, but thought I would ask stackoverflow as well
Hello! I'm new to apollo (and graphql as a whole) and am having some questions about SSR / SSG. I conceptually know what SSR/SSG is and how it works, but not so much with apollo-client.
I've tried searching and scouring the web for which way to do this correctly and have seen both versions with little explanation of why, so my goal with this post to have a place to point and go "This is why you do one over the other".
What are the upsides / downsides between doing
This is a mix of TypeScript and psuedo-code please don't critique syntax kthx
// apolloClient.ts
const client = new ApolloClient({
link: new HttpLink({ uri: '/graphql' }),
cache: new InMemoryCache(),
});
// component.tsx
import client from '../apolloClient';
const Component: FunctionalComponent = ({ data }) => {
...
}
export const getServerSideProps: GetServerSideProps = async () => {
const { data } = client.query(...);
return {
props: { data }
}
}
// app.tsx
import client from './client';
const MyApp: NextComponentType<AppContext, AppInitialProps, AppProps> = ({ Component, pageProps }) => (
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
);
VS
// apolloClient.ts
const createClient = () => new ApolloClient({
link: new HttpLink({ uri: '/graphql' }),
cache: new InMemoryCache(),
ssrMode: typeof window === 'undefined',
});
let client: ApolloClient<NormalizedCacheObject>;
const initalizeApollo = (initalState?: NormalizedCacheObject) => {
const apolloClient = client ?? createClient();
if (initalState) {
apolloClient.cache.restore({
...apolloClient.cache.extract(),
...initalState,
});
}
if (typeof window === 'undefined') return apolloClient;
client ??= apolloClient;
return client;
}
const useApollo = (initalState?: NormalizedCacheObject) => useMemo(() => initalizeApollo(initalState), [initalState]);
// component.tsx
import { useQuery } from 'apollo-client';
import useApollo from '../apolloClient';
const Component = () => {
const { data } = useQuery(...);
}
export const getServerSideProps: GetServerSideProps = async () => {
const client = useApollo();
await client.query(...);
return {
props: { initalApolloState: client.cache.extract() }
}
}
// app.tsx
const MyApp: NextComponentType<AppContext, AppInitialProps, AppProps> = ({ Component, pageProps }) => {
const client = useApollo(pageProps.initalApolloState);
return (
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
)
};
This is my own "I don't understand" portion of this discussion
To me it seems doing it the second way (with SSR?) you're having to run queries twice and write a lot of extra code to get the same effect? What are the performance / safety / any benefits at all to either method.
Thanks!
Wait, you want me to put my data where!? Figuring out how to configure Apollo Client with Next.js can be a bit confusing. This confusion stems from the fact that there are three ways to fetch and render data: static, server-side, and client-side.
I would definitely still use Next.js regardless of ssr/seo stuff. The framework has still so many benefits, and if you don't need ssr, there's no extra boilerplate at all, just use Apollo client as you usually would.
This is because the cached data from that query never makes it into pageProps [APOLLO_STATE_PROP_NAME] (following the official example), since it was executed from a React component rather than from getStaticProps or getServerSideProps.
The Apollo Client is a state management client that allows you to manage both local and remote data with GraphQL and you can use it to fetch, cache, and modify application data. So, without further ado, let’s get started. First, let’s look at why we should use the Apollo Client with Next.js. There are three key reasons to use the Apollo Client:
Your first approach is more in line with what Next is trying to do. It wants to pull data at build time for pages via getStaticProps
(SSG) or getServerSideProps
(SSR). The idea is that it will generate pages on the server statically whenever it can.
Apollo Client doesn't need to be referenced in the getStaticProps
/getServerSideProps
call. I think you could get away with using Context and not even need Apollo Client the way your code is written.
Where I use Apollo in Next apps is when I need to pull data into components. Next doesn't really have an answer for that but it's what Apollo does really well. A good use case is a menu that appears on every page. You don't want to trigger a site-wide static regeneration if you change on menu item. Apollo will keep all the pages fresh and won't trigger Next to render again.
Outline of what I have been doing in this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With