Skip to content

Releases: Shopify/hydrogen

[email protected]

30 Oct 21:00
c9a7e11
Compare
Choose a tag to compare

Patch Changes

@shopify/[email protected]

30 Oct 21:00
c9a7e11
Compare
Choose a tag to compare

Patch Changes

@shopify/[email protected]

30 Oct 14:27
fcac4ab
Compare
Choose a tag to compare

Patch Changes

[email protected]

29 Oct 17:05
845a7f6
Compare
Choose a tag to compare

Patch Changes

  • Stabilize getSitemap, getSitemapIndex and implement on skeleton (#2589) by @juanpprieto

    1. Update the getSitemapIndex at /app/routes/[sitemap.xml].tsx
    - import {unstable__getSitemapIndex as getSitemapIndex} from '@shopify/hydrogen';
      import {getSitemapIndex} from '@shopify/hydrogen';
    1. Update the getSitemap at /app/routes/sitemap.$type.$page[.xml].tsx
    - import {unstable__getSitemap as getSitemap} from '@shopify/hydrogen';
      import {getSitemap} from '@shopify/hydrogen';

    For a reference implementation please see the skeleton template sitemap routes

  • Breaking change by @wizardlyhel

    Set up Customer Privacy without the Shopify's cookie banner by default.

    If you are using Shopify's cookie banner to handle user consent in your app, you need to set withPrivacyBanner: true to the consent config. Without this update, the Shopify cookie banner will not appear.

      return defer({
        ...
        consent: {
          checkoutDomain: env.PUBLIC_CHECKOUT_DOMAIN,
          storefrontAccessToken: env.PUBLIC_STOREFRONT_API_TOKEN,
           withPrivacyBanner: true,
          // localize the privacy banner
          country: args.context.storefront.i18n.country,
          language: args.context.storefront.i18n.language,
        },
      });
  • Update to 2024-10 SFAPI (#2570) by @wizardlyhel

  • Breaking change by @frandiox

    Update createWithCache to make it harder to accidentally cache undesired results. request is now mandatory prop when initializing createWithCache.

    // server.ts
    export default {
      async fetch(
        request: Request,
        env: Env,
        executionContext: ExecutionContext,
      ): Promise<Response> {
        try {
          // ...
    -     const withCache = createWithCache({cache, waitUntil});
          const withCache = createWithCache({cache, waitUntil, request});

    createWithCache now returns an object with two utility functions: withCache.run and withCache.fetch. Both have a new prop shouldCacheResult that must be defined.

    The original withCache callback function is now withCache.run. This is useful to run multiple fetch calls and merge their responses, or run any arbitrary code. It caches anything you return, but you can throw if you don't want to cache anything.

      const withCache = createWithCache({cache, waitUntil, request});
    
      const fetchMyCMS = (query) => {
    -    return withCache(['my-cms', query], CacheLong(), async (params) => {
         return withCache.run({
           cacheKey: ['my-cms', query],
           cacheStrategy: CacheLong(),
           // Cache if there are no data errors or a specific data that make this result not suited for caching
           shouldCacheResult: (result) => !result?.errors,
         }, async(params) => {
          const response = await fetch('my-cms.com/api', {
            method: 'POST',
            body: query,
          });
          if (!response.ok) throw new Error(response.statusText);
          const {data, error} = await response.json();
          if (error || !data) throw new Error(error ?? 'Missing data');
          params.addDebugData({displayName: 'My CMS query', response});
          return data;
        });
      };

    New withCache.fetch is for caching simple fetch requests. This method caches the responses if they are OK responses, and you can pass shouldCacheResponse, cacheKey, etc. to modify behavior. data is the consumed body of the response (we need to consume to cache it).

    const withCache = createWithCache({cache, waitUntil, request});
    
    const {data, response} = await withCache.fetch<{data: T; error: string}>(
      'my-cms.com/api',
      {
        method: 'POST',
        headers: {'Content-type': 'application/json'},
        body,
      },
      {
        cacheStrategy: CacheLong(),
        // Cache if there are no data errors or a specific data that make this result not suited for caching
        shouldCacheResponse: (result) => !result?.error,
        cacheKey: ['my-cms', body],
        displayName: 'My CMS query',
      },
    );
  • Breaking change by @wizardlyhel

    Deprecate usages of product.options.values and use product.options.optionValues instead.

    1. Update your product graphql query to use the new optionValues field.
      const PRODUCT_FRAGMENT = `#graphql
        fragment Product on Product {
          id
          title
          options {
            name
    -        values
             optionValues {
               name
             }
          }
    1. Update your <VariantSelector> to use the new optionValues field.
      <VariantSelector
        handle={product.handle}
    -    options={product.options.filter((option) => option.values.length > 1)}
         options={product.options.filter((option) => option.optionValues.length > 1)}
        variants={variants}
      >
  • Updated dependencies [d97cd56e, 809c9f3d, 8c89f298, a253ef97, 84a66b1e, 227035e7, ac12293c, c7c9f2eb, 76cd4f9b, 8337e534]:

@shopify/[email protected]

29 Oct 17:05
845a7f6
Compare
Choose a tag to compare

Patch Changes

@shopify/[email protected]

29 Oct 17:05
845a7f6
Compare
Choose a tag to compare

Minor Changes

  • [Breaking change] by @wizardlyhel

    Support worker compatibility date that aligns with SFAPI release.

    Starting from this major version, on each deploy to Oxygen, Hydrogen will be on Cloudflare worker compatibility date 2024-10-01. Onwards, Hydrogen will update worker compatibility date on every SFAPI release.

    There is no specific project update that needs to be done in order to get this feature. However, please ensure your project is working properly in an Oxygen deployment when updating to this Hydrogen version. (#2380)

@shopify/[email protected]

29 Oct 17:05
845a7f6
Compare
Choose a tag to compare

Patch Changes

  • Add optional headers param for logout redirect (#2602) by @coryagami

  • Stabilize getSitemap, getSitemapIndex and implement on skeleton (#2589) by @juanpprieto

    1. Update the getSitemapIndex at /app/routes/[sitemap.xml].tsx
    - import {unstable__getSitemapIndex as getSitemapIndex} from '@shopify/hydrogen';
      import {getSitemapIndex} from '@shopify/hydrogen';
    1. Update the getSitemap at /app/routes/sitemap.$type.$page[.xml].tsx
    - import {unstable__getSitemap as getSitemap} from '@shopify/hydrogen';
      import {getSitemap} from '@shopify/hydrogen';

    For a reference implementation please see the skeleton template sitemap routes

  • Update <ProductPrice> to remove deprecated code usage for priceV2 and compareAtPriceV2. Remove export for getCustomerPrivacy. (#2601) by @wizardlyhel

  • Breaking change by @wizardlyhel

    Set up Customer Privacy without the Shopify's cookie banner by default.

    If you are using Shopify's cookie banner to handle user consent in your app, you need to set withPrivacyBanner: true to the consent config. Without this update, the Shopify cookie banner will not appear.

      return defer({
        ...
        consent: {
          checkoutDomain: env.PUBLIC_CHECKOUT_DOMAIN,
          storefrontAccessToken: env.PUBLIC_STOREFRONT_API_TOKEN,
           withPrivacyBanner: true,
          // localize the privacy banner
          country: args.context.storefront.i18n.country,
          language: args.context.storefront.i18n.language,
        },
      });
  • Update to 2024-10 SFAPI (#2570) by @wizardlyhel

  • Breaking change by @frandiox

    Update createWithCache to make it harder to accidentally cache undesired results. request is now mandatory prop when initializing createWithCache.

    // server.ts
    export default {
      async fetch(
        request: Request,
        env: Env,
        executionContext: ExecutionContext,
      ): Promise<Response> {
        try {
          // ...
    -     const withCache = createWithCache({cache, waitUntil});
          const withCache = createWithCache({cache, waitUntil, request});

    createWithCache now returns an object with two utility functions: withCache.run and withCache.fetch. Both have a new prop shouldCacheResult that must be defined.

    The original withCache callback function is now withCache.run. This is useful to run multiple fetch calls and merge their responses, or run any arbitrary code. It caches anything you return, but you can throw if you don't want to cache anything.

      const withCache = createWithCache({cache, waitUntil, request});
    
      const fetchMyCMS = (query) => {
    -    return withCache(['my-cms', query], CacheLong(), async (params) => {
         return withCache.run({
           cacheKey: ['my-cms', query],
           cacheStrategy: CacheLong(),
           // Cache if there are no data errors or a specific data that make this result not suited for caching
           shouldCacheResult: (result) => !result?.errors,
         }, async(params) => {
          const response = await fetch('my-cms.com/api', {
            method: 'POST',
            body: query,
          });
          if (!response.ok) throw new Error(response.statusText);
          const {data, error} = await response.json();
          if (error || !data) throw new Error(error ?? 'Missing data');
          params.addDebugData({displayName: 'My CMS query', response});
          return data;
        });
      };

    New withCache.fetch is for caching simple fetch requests. This method caches the responses if they are OK responses, and you can pass shouldCacheResponse, cacheKey, etc. to modify behavior. data is the consumed body of the response (we need to consume to cache it).

    const withCache = createWithCache({cache, waitUntil, request});
    
    const {data, response} = await withCache.fetch<{data: T; error: string}>(
      'my-cms.com/api',
      {
        method: 'POST',
        headers: {'Content-type': 'application/json'},
        body,
      },
      {
        cacheStrategy: CacheLong(),
        // Cache if there are no data errors or a specific data that make this result not suited for caching
        shouldCacheResponse: (result) => !result?.error,
        cacheKey: ['my-cms', body],
        displayName: 'My CMS query',
      },
    );
  • Breaking change by @wizardlyhel

    Deprecate usages of product.options.values and use product.options.optionValues instead.

    1. Update your product graphql query to use the new optionValues field.
      const PRODUCT_FRAGMENT = `#graphql
        fragment Product on Product {
          id
          title
          options {
            name
    -        values
             optionValues {
               name
             }
          }
    1. Update your <VariantSelector> to use the new optionValues field.
      <VariantSelector
        handle={product.handle}
    -    options={product.options.filter((option) => option.values.length > 1)}
         options={product.options.filter((option) => option.optionValues.length > 1)}
        variants={variants}
      >
  • Add utility functions decodeEncodedVariant and isOptionValueCombinationInEncodedVariant for parsing product.encodedVariantExistence and product.encodedVariantAvailability fields. (#2425) by @lhoffbeck

  • Breaking change by @wizardlyhel

    Update all cart mutation methods from createCartHandler to return cart warnings.

    As of API version 2024-10, inventory errors about stock levels will no longer be included in the userErrors of cart mutations. Inventory errors will now be available in a new return field warnings and will contain explicit code values of MERCHANDISE_NOT_ENOUGH_STOCK or MERCHANDISE_OUT_OF_STOCK. Reference: https://shopify.dev/changelog/cart-warnings-in-storefront-api-cart

  • Updated dependencies [8c89f298, 84a66b1e, 76cd4f9b]:

@shopify/[email protected]

29 Oct 17:05
845a7f6
Compare
Choose a tag to compare

Patch Changes

  • Update <ProductPrice> to remove deprecated code usage for priceV2 and compareAtPriceV2. Remove export for getCustomerPrivacy. (#2601) by @wizardlyhel

  • Update to 2024-10 SFAPI (#2570) by @wizardlyhel

  • Add utility functions decodeEncodedVariant and isOptionValueCombinationInEncodedVariant for parsing product.encodedVariantExistence and product.encodedVariantAvailability fields. (#2425) by @lhoffbeck

@shopify/[email protected]

29 Oct 17:05
845a7f6
Compare
Choose a tag to compare

Patch Changes

  • Checks anywhere in generated filename for "customer" or "caapi" (#2600) by @weotch

@shopify/[email protected]

29 Oct 17:05
845a7f6
Compare
Choose a tag to compare

Patch Changes