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!