--- title: createWithCache description: |- Creates a utility function that executes an asynchronous operation like `fetch` and caches the result according to the strategy provided. Use this to call any third-party APIs from loaders or actions. By default, it uses the `CacheShort` strategy. api_version: 2023-04 api_name: hydrogen source_url: html: 'https://shopify.dev/docs/api/hydrogen/2023-04/utilities/createwithcache' md: 'https://shopify.dev/docs/api/hydrogen/2023-04/utilities/createwithcache.md' --- # create​With​Cache Creates a utility function that executes an asynchronous operation like `fetch` and caches the result according to the strategy provided. Use this to call any third-party APIs from loaders or actions. By default, it uses the `CacheShort` strategy. ## create​With​Cache\_​unstable([options](#arguments-propertydetail-options)​) ### Parameters * options CreateWithCacheOptions required ### Returns * CreateWithCacheReturn\ ### CreateWithCacheOptions * cache An instance that implements the \[Cache API]\(https://developer.mozilla.org/en-US/docs/Web/API/Cache) ```ts Cache ``` * waitUntil The \`waitUntil\` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform. ```ts ExecutionContext ``` ```ts { /** An instance that implements the [Cache API](https://developer.mozilla.org/en-US/docs/Web/API/Cache) */ cache: Cache; /** The `waitUntil` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform. */ waitUntil: ExecutionContext['waitUntil']; } ``` ### CreateWithCacheReturn This is a caching async function. Whatever data is returned from the \`actionFn\` will be cached according to the strategy provided. Use the \`CachingStrategy\` to define a custom caching mechanism for your data. Or use one of the built-in caching strategies: \`CacheNone\`, \`CacheShort\`, \`CacheLong\`. ```ts ( cacheKey: CacheKey, strategy: CachingStrategy, actionFn: () => T | Promise, ) => Promise ``` ### CacheKey The cache key is used to uniquely identify a value in the cache. ```ts string | readonly unknown[] ``` ### CachingStrategy Use the \`CachingStrategy\` to define a custom caching mechanism for your data. Or use one of the pre-defined caching strategies: CacheNone, CacheShort, CacheLong. * mode The caching mode, generally \`public\`, \`private\`, or \`no-store\`. ```ts string ``` * maxAge The maximum amount of time in seconds that a resource will be considered fresh. See \`max-age\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:\~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage). ```ts number ``` * staleWhileRevalidate Indicate that the cache should serve the stale response in the background while revalidating the cache. See \`stale-while-revalidate\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate). ```ts number ``` * sMaxAge Similar to \`maxAge\` but specific to shared caches. See \`s-maxage\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage). ```ts number ``` * staleIfError Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See \`stale-if-error\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error). ```ts number ``` ```ts AllCacheOptions ``` Examples ### Examples * #### Example code ##### Description I am the default example ##### JavaScript ```js // In your app's `server.ts` file: import * as remixBuild from '@remix-run/dev/server-build'; import {createWithCache_unstable, CacheLong} from '@shopify/hydrogen'; // Use another `createRequestHandler` if deploying off oxygen import {createRequestHandler} from '@shopify/remix-oxygen'; export default { async fetch(request, env, executionContext) { const cache = await caches.open('my-cms'); const withCache = createWithCache_unstable({ cache, waitUntil: executionContext.waitUntil, }); // Create a custom utility to query a third-party API: const fetchMyCMS = (query) => { // Prefix the cache key and make it unique based on arguments. return withCache(['my-cms', query], CacheLong(), async () => { return await ( await fetch('my-cms.com/api', { method: 'POST', body: query, }) ).json(); }); }; const handleRequest = createRequestHandler({ build: remixBuild, mode: process.env.NODE_ENV, getLoadContext: () => ({ /* ... */ fetchMyCMS, }), }); return handleRequest(request); }, }; ``` ##### TypeScript ```ts // In your app's `server.ts` file: import * as remixBuild from '@remix-run/dev/server-build'; import {createWithCache_unstable, CacheLong} from '@shopify/hydrogen'; // Use another `createRequestHandler` if deploying off oxygen import {createRequestHandler} from '@shopify/remix-oxygen'; export default { async fetch( request: Request, env: Record, executionContext: ExecutionContext, ) { const cache = await caches.open('my-cms'); const withCache = createWithCache_unstable({ cache, waitUntil: executionContext.waitUntil, }); // Create a custom utility to query a third-party API: const fetchMyCMS = (query: string) => { // Prefix the cache key and make it unique based on arguments. return withCache(['my-cms', query], CacheLong(), async () => { return await ( await fetch('my-cms.com/api', { method: 'POST', body: query, }) ).json(); }); }; const handleRequest = createRequestHandler({ build: remixBuild, mode: process.env.NODE_ENV, getLoadContext: () => ({ // Make sure to update remix.env.d.ts to include `fetchMyCMS` fetchMyCMS, }), }); return handleRequest(request); }, }; ```