Caching API responses
Modern CDNs can cache API responses, significantly reducing the load on your middleware and improving the performance of your application, even if the HTML itself is not cached. Please note, that due to the nature of the CDN cache, only the traffic between the browser and the middleware will be cached. The requests sent during the SSR process will not be cached.
How to enable caching API responses
Set Cache-Control header in the middleware
1
Setup the extension for all the integrations that you want to cache.
// apps/storefront-middleware/integrations/<integration>/extensions/cdn.ts
import middlewareHeaders from '@vsf-enterprise/middleware-headers';
const DEFAULT_MIDDLEWARE_TTL = 60 * 5;
const cacheControl =
process.env.CACHE_CONTROL ||
`public, max-age=0, s-maxage=${DEFAULT_MIDDLEWARE_TTL}, must-revalidate`;
export const cdnExtension = middlewareHeaders({
cacheControl,
isNamespaced: false,
methods: {}, // will use default cache control configuration
});
2
Re-export the newly added extension in the barrel file
`apps/storefront-middleware/integrations/<integration>/extensions/index.ts`;
export * from './unified';
export * from './multistore';
export * from './cdn';
3
Plug the extension into your integration:
// apps/storefront-middleware/integrations/<integration>/config.ts
import { multistoreExtension, unifiedApiExtension } from './extensions'; import { cdnExtension, multistoreExtension, unifiedApiExtension } from './extensions'; ...
extensions: (extensions: ApiClientExtension[]) => [
...extensions,
unifiedApiExtension,
cdnExtension, ...(IS_MULTISTORE_ENABLED === 'true' ? [multistoreExtension] : []),
],
Keeping custom endpoints cacheable
If you define any new endpoints or want to customize the cache control for the existing ones, you can do it by following the steps below.
1
Define cache control for the new endpoint in the middleware
// apps/storefront-middleware/integrations/<integration>/extensions/cdn.ts
import middlewareHeaders from '@vsf-enterprise/middleware-headers';
const DEFAULT_MIDDLEWARE_TTL = 60 * 5;
const cacheControl =
process.env.CACHE_CONTROL ||
`public, max-age=0, s-maxage=${DEFAULT_MIDDLEWARE_TTL}, must-revalidate`;
export const cdnExtension = middlewareHeaders({
cacheControl,
isNamespaced: false,
methods: {
myNewEcommerceEndpoint: {
cacheControl: `public, max-age=0, s-maxage=${60 * 15}, must-revalidate`,
},
},
});
2
Tell the SDK to send the request via GET method. In SDK config file.
// apps/storefront-unified-nextjs/sdk/config.ts
export function getSdkConfig() {
return defineSdkConfig(
({ buildModule, config, getRequestHeaders, middlewareModule }) => ({
commerce: buildModule(middlewareModule<CommerceEndpoints>, {
// Default methods config that configures which methods should be sent via GET requests
methodsRequestConfig: {
...config.defaultMethodsRequestConfig.unifiedCommerce
.middlewareModule,
myNewEcommerceEndpoint: {
method: 'GET',
},
},
}),
})
);
}
You should not cache endpoints that are mutations, respond with sensitive information, or return different data for each user.
Caching mutation endpoints would prevent mutations from being executed. Caching endpoints that respond with sensitive information can pose security risks, as cached data might be accessed by unauthorized users. Endpoints that return different data for each user should not be cached to prevent users from seeing data that belongs to someone else, which can lead to privacy violations and incorrect application behavior.
Validating if we did everything correctly
1
Run the project. If you are using Next.js, then you have to run it in a prod mode. So yarn build && yarn start
from within the project root.
2
Open the network tab of your browser’s dev tools
3
Verify that the selected set of requests to the middleware are sent as GET requests. The Cache-Control
header should be attached to the response (i.e. getProductDetails
is one of the default requests that is usually cached, it is usually triggered on the product details page ). The Cache-Control
header should contain the value that was set by you. If you didn't set any specific value, then the default value for s-maxage
will be non-zero.