Apollo Client is a popular GraphQL client that can cache the results of your queries, among many other features. If you have an entirely client-side rendered (CSR) front-end app and want to do all your data fetching in the browser, you can simply start off with an empty Apollo Client cache and populate it with data as GraphQL requests execute.
But what if you want to use server-side rendering (SSR), static site generation (SSG), or incremental static regeneration (ISR), though? How can you fetch data ahead of time on the server? Can the Apollo Client’s cache initialize with that data on the client so that your queries don’t need to be rerun?
Thankfully, there is a way to fetch data on the server, populate Apollo Client’s cache, send that cache data to the client, and use it to “rehydrate” or initialize Apollo Client’s cache in the browser. Cache rehydration gives the benefits of SSR/SSG/ISR (a fully rendered HTML document on the initial page load, great SEO, etc.). Best of all, you still have the data in Apollo Client’s cache. This prevents your app from making unnecessary network requests for data you already have.
In this blog post, we’ll cover how to set up Apollo Client cache rehydration in a Next.js app.
Before setting up cache rehydration, fulfill the following prerequisites:
- Clone down the repo to your machine: https://github.com/kellenmace/apollo-client-cache-rehydration-in-next-js
yarn) to install the project’s dependencies.
- Create a
.env.localfile in the root directory with this variable defined:
NEXT_PUBLIC_WORDPRESS_API_URL=http://my-local-site.local/graphql. Swap out
http://my-local-site.localwith the domain of a WordPress site that has WPGraphQL installed.
npm run devto get the app up and running locally.
Server-side Rendering (SSR) through the Apollo client follows this approach:
- Use Apollo Client’s
getDataFromTree()function to get the results for all queries throughout your entire component tree for the current page.
- Extract Apollo Client’s cache and send that data to the client as a global
- When Apollo Client initializes on the client, call its
new InMemoryCache().restore()function, passing in the
window.APOLLO_STATEobject to seed it with the cache data from the server.
Although using the SSR approach works well with Next.js, the recommended way to do Apollo Client cache rehydration differs from that. We will instead do this:
- Use Next’s
getServerSideProps()function to do our data fetching and populate Apollo Client’s cache.
- Extract Apollo Client’s cache and add it as a
pagePropsprop for the current page.
- When Apollo Client initializes on the client, call its
new InMemoryCache().restore()function, passing in the cache data from the server.
For more information on how the Apollo client works, check out this official Next.js example project. We’ll use that same approach for our purposes, except the code examples will be written in TypeScript rather than JS, and all the data fetching examples will be specific to WordPress and WPGraphQL.
Install & Configure Apollo Client
Per Apollo Client’s getting started documentation, the
graphql NPM are already installed. The
lodash packages have also been installed, which our project leverages.
To start configuring the client, open the
lib/apolloClient.ts file in a code editor. It looks like this:
Let’s walk through each of those function definitions.
This function is responsible for creating a new instance of Apollo Client.
We set Apollo Client’s
ssrMode option to
true if the code is running on the server, and to
false if it’s running on the client.
uri: process.env.NEXT_PUBLIC_WORDPRESS_API_URL line tells Apollo Client to use the GraphQL endpoint defined in your
.env.local file for all network requests.
As its name suggests, this function initializes Apollo Client. It merges the initial state (data passed in from
getServerSideProps()) with the existing client-side Apollo cache, then sets that new, merged data set as the new cache for Apollo Client.
This function takes the
pageProps returned from
getServerSideProps() for the current page and adds to them Apollo’s cache data. From there, Next.js takes care of passing Apollo’s cache data, along with any other page-specific props into the page component.
This function calls
initializeApollo() to get an instance of Apollo Client that has Apollo’s cache data added to it. This client is ultimately passed in as a prop to the
ApolloProvider that Apollo Client provides.
Render an ApolloProvider
_app.tsx, we call
useApollo() to get a new instance of Apollo Client, passing to it the
pageProps for the current page. The
apolloClient instance is then passed in as a prop to the
ApolloProvider component, which wraps our application.
How to Use in Page Components
Let’s see how we can use this Apollo Client cache rehydration superpower in our Next.js page components.
pages/ssg.tsx. A simplified version of that file looks like this:
Inside of Next.js’
getStaticProps() function, we call
initializeApollo() to get an instance of Apollo Client that we can use for making GraphQL requests.
We then call the
apolloClient.query() method, passing in the exact same query and variables that are used inside of our
SSG page component when it calls the
useQuery() hook. You’ll notice that we’re not even using the return value that
apolloClient.query() provides. This is because we don’t need it – we’re only calling
apolloClient.query() to populate Apollo Client’s cache with the data for the queries executed.
SSG page component is rendered in the browser and the
useQuery() hook is called, Apollo Client will “see” that the data for the query being executed already exists it its cache, and will use that data instead of making a network request. This will result in the content on the page rendering immediately. Visit http://localhost:3000/ssg in your browser, open up the Network tab in the DevTools and refresh the page to confirm that no client-side GraphQL requests execute.
More info on Next.js’
getStaticProps() function can be found here: https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation.
pages/ssr.tsx and visit http://localhost:3000/ssr. You can see that this file functions exactly the same as
ssg.tsx, except that Next.js passes in the page props on every request since we’re using
getServerSideProps() instead of
getStaticProps(). Again, you can open up the Network tab in the DevTools and refresh the page to confirm that no client-side GraphQL requests execute.
More info on Next.js’
getServerSideProps() function can be found here: https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering.
To prove that we still have the option to do data fetching on the client, if desired, open up
pages/csr.tsx and visit http://localhost:3000/csr. You can see that this page does not fetch any data on the server, since we’re not using
getServerSideProps(). If you open up the Network tab in the DevTools and refresh the page, you can confirm that the GraphQL network requests execute client-side when the page first loads. You can do this if you want your request to run in the browser only, and not on the server.
Mixed SSG + CSR Page
Finally, open up
pages/blog.tsx. Make sure you have eleven or more posts created in your WordPress backend, then visit http://localhost:3000/blog.You can see that inside of
getStaticProps(), an Apollo Client query is executed to get the initial list of ten blog posts, which immediately get rendered to the page when it loads. If more posts exist in the WordPress backend, the user is presented with a
Load more button. Clicking this button results in Apollo Client’s
fetchMore() function being called, which fires off a network request to get the next five posts and appends them to the list. Once all posts have been loaded, the user sees an
✅ All posts loaded message.
blog.tsx page shows how you can fetch some data on the server to populate Apollo’s cache. Also, the markup appears instantly when the page loads on the front-end. After, the page fires subsequent client-side requests to fetch additional data, adding it to Apollo’s cache..
How to Use this Code in Your Projects
In order to use Apollo Client for SSG/SSR/ISR in a Next.js project, you’ll need to follow these steps:
lib/apolloClient.tsinto your project.
As stated above, set the
process.env.NEXT_PUBLIC_WORDPRESS_API_URLvariable to reference the GraphQL endpoint of your headless WordPress backend.
The object containing
typePoliciesthat is being passed into
new InMemoryCache()in this file can be omitted if you’re not doing any pagination in your project (such as the
fetchMore()pagination demonstrated on the
useApollo(pageProps)to get an instance of Apollo Client, then pass that in as a prop to the
<ApolloProvider />component, as shown above.
- Mimic the page components in the /pages directory of this project, depending on whether you want your pages to do their data fetching at build time (see
ssg.tsx), at request time on the server (see
ssr.tsx), on the client only (see
csr.tsx), or a mixture of those (see
I hope this walk-through helps you with leveraging Apollo Client for SSG/SSR/ISR data fetching on your next Next.js project.
And that’s it! Thanks so much for giving this post a read, and please reach out to us with any questions you have! ????