Next.js Caching Features
Catalyst uses several caching mechanisms in Next.js, including request memoization and the Data Cache. These are designed to improve performance, reduce redundant requests, and lower rendering costs. For more details, check out the Caching documentation (opens in a new tab) on Next.js.
Request Memoization
Catalyst utilizes Next.js’s request memoization (opens in a new tab) to ensure data is fetched once during the React render cycle, even if requested multiple times within the component tree. This reduces unnecessary network requests, improving performance across your storefront.
For data fetching that might potentially be performed multiple times within a single page request, we wrap async functions with the cache
utility. This memoizes the result and returns the cached value on subsequent calls.
Example:
export const getProduct =
cache(
async (entityId: number, customerAccessToken?: string) => {
const { data } = await client.fetch({
...
});
return data.site.product;
}
);
Data Cache
Next.js extends the native fetch
API to cache data across requests, allowing cached data reuse until it's invalidated. This ensures faster response times and reduces the load on external APIs, like the BigCommerce GraphQL Storefront API.
Data Cache behavior is controlled by the fetchOptions
parameter passed to the Catalyst API Client (opens in a new tab).
Example:
import { revalidate } from '~/client/revalidate-target';
const { data } = await client.fetch({
document: ProductQuery,
fetchOptions: { next: { revalidate } },
});
fetchOptions
parameters are passed directly to fetch
and follow the standard Next.js conventions. See the Next.js docs on the cache (opens in a new tab) and next.revalidate (opens in a new tab) parameters.
Anonymous vs. Customer-Specific Requests
By default, Catalyst utilizes the Data Cache for fetch
requests for anonymous data, which account for the vast majority of requests on a typical storefront.
This setup ensures non-unique, repeatable requests benefit from caching while requests affected by customer context are appropriately dynamic.
- Cacheable data: For data that is cacheable, such as product data,
fetchOptions
is configured to allow caching for guests and disallow it for logged-in customers. - Non-cacheable data: For data that is never appropriate to cache, such as cart data,
fetchOptions
is always configured to disallow caching.
This configuration is passed on a per-request basis, so you can configure caching behavior to best suit the needs of a particular fetch.
Recommended Practices
To ensure optimal performance, when crafting your own API requests, use fetchOptions
to take advantage of the Data Cache for any anonymous data or disable it for customer-specific data.
Example of catalog data fetch:
import { getSessionCustomerAccessToken } from '~/auth';
import { revalidate } from '~/client/revalidate-target';
const customerAccessToken = await getSessionCustomerAccessToken();
const { data } = await client.fetch({
document: ProductQuery,
customerAccessToken,
fetchOptions: customerAccessToken ? { cache: 'no-store' } : { next: { revalidate } },
});
Example of cart data fetch:
import { getSessionCustomerAccessToken } from '~/auth';
const customerAccessToken = await getSessionCustomerAccessToken();
const { data } = await client.fetch({
document: CartQuery,
customerAccessToken,
fetchOptions: {
cache: 'no-store',
},
});
Controlling Cache Duration
For data that is not customer-specific, we usually apply a default caching strategy of 1 hour, adjustable via the revalidate
property in the fetch
function. Most functions use a value based on the DEFAULT_REVALIDATE_TARGET
environment variable. Adjust this value depending on your store's needs. Here’s a recommendation guide:
Traffic | Product/Category Updates | Recommendation |
---|---|---|
High | High | 1-8 hours |
High | Low | 8-24 hours |
Low | High | 1-8 hours |
Low | Low | 24-48 hours |
The lower the DEFAULT_REVALIDATE_TARGET
, the more requests your store will make to the BigCommerce API, leading to rate limiting and increased costs. Monitor API usage and adjust the DEFAULT_REVALIDATE_TARGET
accordingly.
Rate Limiting
BigCommerce GraphQL mutations are rate-limited by the request IP. Catalyst adds the shopper’s IP address to the request headers when a fetch
request has a cache
value of no-store
or no-cache
. This helps prevent rate limiting and ensures your store can handle high traffic.