In this article, I will discuss a common issue and best practices when using the Apollo client with Atlas, WP Engine’s headless WordPress hosting platform.
The Apollo Client 🧑🚀
The Apollo client is a popular comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. It has features you can use for fetching, modifying application data, and caching. This article’s focus is the caching mechanism in Apollo.
If you need foundational knowledge of Apollo, please visit their docs.
Usage with Next.js and Headless WordPress
Next.js is the most popular open-source front-end Javascript framework. Most developers that have adopted a Headless WordPress architecture choose Next.js because it allows you to choose and pick how to render and fetch your data from WordPress. You can use Static Site Generation, Server Side Rendering, or Incremental Static Regeneration.
Out of the box, Next.js uses its getStaticProps
function which is the method for statically generating your site at build time. You can also choose getServerSideProps
which is the opposite of static generation. This tells the Next.js component to populate the props and render them into a static HTML page at run time.
Within these methods, it is common to use the WPGraphQL API and GraphQL with Apollo to fetch the page data from WordPress.
Here is the common configuration from the Apollo docs below:
import { InMemoryCache, ApolloClient } from '@apollo/client';
const client = new ApolloClient({
//..other arguements...
cache: new InMemoryCache(options)
})
Code language: JavaScript (javascript)
What you would expect when using getStaticProps
is for the WordPress data to be fresh and updated upon every rebuild of the page and site.
On the flip side of that, When you use getServerSideProps
and fetch the WordPress data at runtime, you should see the fresh data immediately because the server is doing the work upon every user’s request.
One issue we have seen developers run into is seeing stale WordPress data show up in their front-end application, something that can happen with Apollo’s default caching policy. And this is not ideal when you have mission-critical sites that rely on up-to-date data as close to real-time as possible.
This is where the Apollo client configuration comes into play.
Catching the Apollo Cache 💸
The Apollo client has its own caching mechanism and this is where the issue lies. Most people using Apollo might be unaware that when creating an Apollo custom configuration in their project, it has its own caching layer that can affect your data freshness, in relation to what hosting platform you are using. In this article’s case, we are talking about the Atlas platform.
Now, some serverless platforms will naturally run the Apollo cache to be shorter-lived. In Atlas, it runs a full node server and the outcome of this is a longer-lived Apollo cache.
Configuration with Atlas
Our very own solutions architect Jordan Maslyn created this code snippet for Atlas users to alleviate the issue when using Apollo:
import {
ApolloClient,
InMemoryCache,
HttpLink,
ApolloLink,
} from "@apollo/client";
const link = ApolloLink.from([
new HttpLink({
uri: `${process.env.NEXT_PUBLIC_WORDPRESS_API_URL}/graphql`,
useGETForQueries:
process.env.CACHE_GRAPHQL_RESPONSES !== "false" ? true : false,
}),
]);
export const client = new ApolloClient({
link,
cache: new InMemoryCache(),
defaultOptions: {
query: {
fetchPolicy:
process.env.CACHE_GRAPHQL_RESPONSES !== "false"
? "cache-first"
: "network-only",
},
},
});
Code language: JavaScript (javascript)
Let’s break down what is happening in Jordan’s code snippet.
The Apollo client uses HttpLink
to send GraphQL operations to a server over HTTP.
The link supports both POST
and GET
requests, and it can modify HTTP options on a per-query basis.
The code block above starts with an Apollo Link that equals the new link variable and uses HttpLink
. The useGETForQueries
key is a constructor option that Httplink
accepts.
If set to true, HttpLink
uses GET
requests instead of POST
requests to execute query operations (but not mutation operations). GET
requests can allow us to leverage some default caching from the protocol (and helps improve the performance and scalability of your WordPress server!), but if we are interested in prioritizing data freshness over performance/scalability, we will want to disable that feature.
The next thing to focus on is the fetchPolicy
key. This key defines how Apollo Client uses the cache for a particular query. The default policy is cache-first, which means Apollo Client checks the cache to see if the result is present before making a network request.
If the result is present, no network request occurs. Within the const variable that is exported as the new Apollo Client, we have an environment variable called CACHE_GRAPHQL_RESPONSES which is set to “false”.
This means that wherever an Atlas customer instantiates their Apollo client, it will bypass the Apollo Cache. By using the “network-only” fetchPolicy
, we can deter Apollo from caching responses which prioritizes data freshness (and allows other layers with more awareness of your content to handle the caching as discussed in the next section).
The Trade-Off
Like everything in web development, there are tradeoffs in any approach you decide to take. Bypassing the Apollo cache will give you the up-to-date, fresh data that you require. However, the trade-off here is that you are not serving cached files which are served quicker by default.
Because you will be running the request on the server, the performance for page load is decreased and you will increase the load on your server. However, there is a new tool that can let you have both!
Optional Solution: ⚡WPGraphQL Smart Cache ⚡
An option to consider is WPGraphQL Smart Cache. This plugin captures the results of GraphQL Requests, stores the response in a cache, and uses the cached response for future requests instead of executing the query and all of its resolvers at each request.
This means you are not evening hitting your WordPress server, in turn decreasing the load and increasing your performance. Above and beyond Apollo’s caching implementation, WPGraphQL Smart Cache knows when you update your content and can purge any related cached responses accordingly.
This lets you continue having the performance and scalability benefits of an API caching layer while also delivering the freshest version of your data as it is requested by your front-end application.
I go into detail about it in my blog post! Please consider this as an option, as this will provide an optional solution for the long-running Apollo Cache on Atlas.
Conclusion 🚀
The powerful combination of Next.js, the Apollo Client, and WPGraphQL can give your developers an amazing developer experience as well as give your users an amazing experience when requesting information from your apps and sites built on these tools.
When using WP Engine’s Atlas, we want to ensure that the tools you use on our platform are fully optimized within the use case of your site especially when it comes to the caching layer, a crucial component of any web development architecture.
Hopefully, if you are an Atlas customer or considering using Atlas and are choosing Next.js and Apollo, you find this helpful. Special thanks to Jordan Maslyn! As always, let us know your thoughts, feedback, and suggestions in our discord! Stoked!