hydrogen/packages/hydrogen/src/framework/docs/cache.md
2021-11-09 17:03:36 -08:00

7.9 KiB
Raw Blame History

Caching is a fundamental building block of a good shopping experience. Combined with streaming server-side rendering, caching ensures that buyers get the quickest response possible while also displaying the latest data.

Hydrogen provides two mechanisms for cache within applications:

Hydrogen also includes default values for each mechanism.

Note: If youre interacting with personalized or private data, then you need to override these defaults to meet your needs.

Cache options

Each mechanism accepts the same cache options API based on the Cache-Control HTTP Header:

export interface CacheOptions {
  maxAge?: number;
  staleWhileRevalidate?: number;
  private?: boolean;
  noStore?: boolean;
}
Name Description
maxAge Correlates with the max-age cache control header. Instructs the cache how long to store an entry.
staleWhileRevalidate Correlates with the stale-while-revalidate cache control header. Instructs the cache how long after an entrys max-Age is acceptable to serve a stale entry. Another request for fresh data is made in the background.
private Defaults to false. Correlates with the private cache control header. If private is set to true, then the entry is cached in a users browser but not at the hosting or edge layer. This is useful for private or customized data.
noStore Defaults to false. Correlates with the no-store cache control header. If noStore is set to true, then the entry is prevented from being cached at any layer. This is useful for private or time-sensitive data.

Sub-request caching

While rendering a page in your Hydrogen app, its common to make one or more sub-requests to Shopify or other third-party data sources within server components. You should use sub-request caching to keep pages loading quickly for end-users. The following example shows how to implement useShopQuery for Shopify Storefront API queries:

{% codeblock file, filename: '/pages/my-products.server.jsx' %}

const {data} = useShopQuery({
  query: QUERY,
  cache: {
    // Cache the data for one second.
    maxAge: 1,
    // Serve stale data for up to nine seconds while getting a fresh response in the background.
    staleWhileRevalidate: 9,
  },
});

{% endcodeblock %}

The following example shows how to implement useQuery for third-party requests:

{% codeblock file, filename: '/pages/my-products.server.jsx' %}

const {data} = useQuery(
  'cache-key',
  async () => await fetch('https://my.3p.com/data.json').then(res => res.json()),
  {
    cache: {
      // Cache the data for one second.
      maxAge: 1,
      // Serve stale data for up to nine seconds while getting a fresh response in the background.
      staleWhileRevalidate: 9,
    },
  }
});

{% endcodeblock %}

When the cached entry becomes stale, if the age of the entry is still within the stale-while-revalidate window, then the stale version is returned and a new version is generated in the background.

Full-page caching

In addition to sub-request caching, its helpful to cache the entire page response at the network edge and in the browser. This is the most useful for pages without dynamic or personalized data, like marketing pages or blog content.

To modify full-page caching options, use the response property passed to the page server component:

{% codeblock file, filename: '/pages/my-products.server.jsx' %}

export default function MyProducts({response}) {
  response.cache({
    // Cache the page for one hour.
    maxAge: 60 * 60,
    // Serve the stale page for up to 23 hours while getting a fresh response in the background.
    staleWhileRevalidate: 23 * 60 * 60,
  });
}

{% endcodeblock %}

Default values

Hydrogen provides sensible defaults for all sub-requests and full-page requests cache options.

By default, each sub-request receives the following cache options:

{
  // Cache the data for one second.
  maxAge: 1,
  // Serve stale data for up to nine seconds while getting a fresh response in the background.
  staleWhileRevalidate: 9,
}

By default, each full-page receives the following cache options:

{
  // Cache the page for one hour.
  maxAge: 60 * 60,
  // Serve the stale page for up to 23 hours while getting a fresh response in the background.
  staleWhileRevalidate: 23 * 60 * 60,
}

Caching in development

Caching is disabled by default during development.

To enable sub-request caching using an in-memory store, pass devCache: true to the second parameter of the Hydrogen Vite plugin:

{% codeblock file, filename: '/vite.config.js' %}

export default defineConfig({
  plugins: [hydrogen(shopifyConfig, {devCache: true})],
});

{% endcodeblock %}

You can also preview the full-page caching headers in the network tab of your browsers developer tools. The response header used is cache-control-preview.

A screenshot of the response headers

Caching in production

Sub-request caching uses an instance of Cache passed to the entry point.

For Worker-based runtimes, you can provide a cache option to handleEvent:

{% codeblock file, filename: '/worker.js' %}

addEventListener('fetch', (event) => {
  try {
    event.respondWith(
      handleEvent(event, {
        // Your implementation of `Cache`. Defaults to `caches.default` for Oxygen support.
        cache: caches.default,

        // ...
      })
    );
  } catch (error) {
    // ...
  }
});

{% endcodeblock %}

For Node.js-based runtimes, you can provide a cache option to hydrogenMiddleware:

{% codeblock file, filename: '/server.js' %}

app.use(
  '*',
  hydrogenMiddleware({
    // You need to provide a `Cache` implementation backed by something like Redis or Memcached.
    cache: customCacheImplementation,
    // ...
  })
);

{% endcodeblock %}

Full-page caching is powered completely by cache-control headers on the Hydrogen response. This means the network edge as well as the users browser is responsible managing full-page cache.

Note: Oxygen caches HTML responses from Hydrogen at the network edge. However, your hosting provider or CDN might not cache HTML responses by default. Make sure to consult with your individual provider to enable HTML caching for your Hydrogen app.

Next steps