Skip to content

Releases: Shopify/hydrogen-v1

@shopify/[email protected]

22 Mar 17:47
3c732da
Compare
Choose a tag to compare

Hydrogen 0.13.0

Please read through the release notes carefully. A lot has changed in this release, especially in regards to app performance. For reference a pull request is available to compare the changes between 0.12.0 and 0.13.0: https://github.com/blittle/hydrogen-migration/pull/2/files

Minor Changes

  • #922 b5eaddc1 Thanks @frehner! - Fragments and their related types have been removed:

    • ExternalVideoFragment and ExternalVideoFragmentFragment
    • Model3DFragment and Model3DFragmentFragment
    • ImageFragment and ImageFragmentFragment
    • MoneyFragment and MoneyFragmentFragment
    • UnitPriceFragment and UnitPriceFragmentFragment
    • VideoFragment and VideoFragmentFragment
    • MetafieldFragment and MetafieldFragmentFragment
    • Seo fragments and types:
      • DefaultPageSeoFragment and DefaultPageSeoFragmentFragment
      • HomeSeoFragment and HomeSeoFragmentFragment
      • ProductSeoFragment and ProductSeoFragmentFragment
      • CollectionSeoFragment and CollectionSeoFragmentFragment
      • PageSeoFragment and PageSeoFragmentFragment
    • MediaFile fragments and types:
      • MediaFileFragment and MediaFileFragmentFragment
      • MediaFileFragment_ExternalVideo_Fragment
      • MediaFileFragment_MediaImage_Fragment
      • MediaFileFragment_Model3d_Fragment
      • MediaFileFragment_Video_Fragment
    • ProductFragment and ProductFragmentFragment

    These fragments have been removed to reduce the chances of over-fetching (in other words, querying for fields you don't use) in your GraphQL queries. Please refer to the Storefront API documentation for information and guides.

  • #912 de0e0d6a Thanks @blittle! - Change the country selector to lazy load available countries. The motivation to do so is that a lot of countries come with the starter template. The problem is 1) the graphql query to fetch them all is relatively slow and 2) all of them get serialized to the browser in each RSC response.

    This change removes availableCountries from the LocalizationProvider. As a result, the useAvailableCountries hook is also gone. Instead, the available countries are loaded on demand from an API route.

    Migratation steps:

    Create an API route to retrieve available countries:

    export async function api(request, {queryShop}) {
      const {
        data: {
          localization: {availableCountries},
        },
      } = await queryShop({
        query: QUERY,
      });
    
      return availableCountries.sort((a, b) => a.name.localeCompare(b.name));
    }
    
    const QUERY = `
      query Localization {
        localization {
          availableCountries {
            isoCode
            name
            currency {
              isoCode
            }
          }
        }
      }
    `;

    Then within your client code, query the API route with a useEffect hook:

    const [countries, setCountries] = useState([]);
    
    useEffect(() => {
      fetch('/api/countries')
        .then((resp) => resp.json())
        .then((c) => setCountries(c))
        .catch((e) => setError(e))
        .finally(() => setLoading(false));
    }, []);

    See an example on how this could be done inside the Hydrogen Example Template country selector

  • #698 6f30b9a1 Thanks @jplhomer! - Basic end-to-end tests have been added to the default Hydrogen template. You can run tests in development:

    yarn test

    Or in continuous-integration (CI) environments:

    yarn test:ci
  • #932 507c5cbf Thanks @jplhomer! - Adds CSS Modules support. Hydrogen now includes a Vite plugin that collects styles for each CSS Module and exports them to a StyleTag component. To use CSS Modules in your Hydrogen app, you must render the style tag in the component along with your styles:

    import * as styles from './styles.module.css';
    
    export default MyComponent() {
      return (
        <div className={styles.wrapper}>
          // A style is rendered inline
          <styles.StyleTag />
          <p>Hello</p>
        </div>
      );
    }

    Explore an example implementation of CSS Modules in GitHub.

  • #846 58c823b5 Thanks @blittle! - ## New <Route> Component

    The <Route> component is available for routes not defined by the file system. The <Route> component must be used within the <Router> component.

    // app.server.jsx
    
    function App({routes, ...serverProps}) {
      return (
        <Suspense fallback={<LoadingFallback />}>
          <ShopifyProvider shopifyConfig={shopifyConfig}>
            <CartProvider>
              <DefaultSeo />
              <Router serverProps={serverProps}>
                <Route path="/custom" page={<CustomRoute />} />
              </Router>
            </CartProvider>
          </ShopifyProvider>
        </Suspense>
      );
    }
    
    function CustomRoute() {
      return <h1>Custom route</h1>;
    }

    <Route> accepts two props:

    Property Type Required Description
    path string Yes The URL path where the route exists. The path can contain variables. For example, /products/:handle.
    page A rendered Server Component reference Yes A reference to a React Server Component that's rendered when the route is active.

    Changes to <Router>

    You can have multiple <Route> and <FileRoutes> components in your app. Hydrogen will only render one route for each request — whichever it finds first. This means the <Router> component no longer takes fallback as a prop. It also doesn't need serverProps. Instead, to render a 404 "Not Found" page, add <Route path="*" page={<NotFound />} /> to your app. Make sure it's the last <Route> defined inside your app:

    function App({routes, ...serverProps}) {
      return (
        <ShopifyProvider shopifyConfig={shopifyConfig}>
          <CartProvider>
            <DefaultSeo />
    -       <Router
    -         fallback={<NotFound response={serverProps.response} />}
    -         serverProps={serverProps}
    -       >
    +       <Router>
              <FileRoutes routes={routes} />
    +         <Route path="*" page={<NotFound />} />
            </Router>
          </CartProvider>
        </ShopifyProvider>
      );
    }

    Changes to <FileRoutes>

    The <FileRoutes> component now accepts two additional optional props:

    Property Type Required Default Value Description
    basePath string No "/" A path that's prepended to all file routes.
    dirPrefix string No "./routes" The portion of the file route path that shouldn't be a part of the URL.

    You need to modify dirPrefix if you want to import routes from a location other than src/routes.

    You can modify basePath if you want to prefix all file routes. For example, you can prefix all file routes with a locale:

    <Router>
      <FileRoutes basePath={`/${locale}`} routes={routes} />
      <Route path="*" page={<NotFound />} />
    </Router>

    New useRouteParams() hook

    You can use the useRouteParams() hook to retrieve the parameters of an active route. The hook is available in both server and client components:

    // products/[handle].server.jsx
    
    import {useRouteParams} from '@shopify/hydrogen';
    
    export default function Product() {
      const {handle} = useRouteParams();
      // ...
    }
    // ProductDetails.client.jsx
    import {useRouteParams} from '@shopify/hydrogen/client';
    
    export default function ProductDetails() {
      const {handle} = useRouteParams();
      // ...
    }
  • #842 626e58ee Tha...

Read more

@shopify/[email protected]

22 Mar 17:47
3c732da
Compare
Choose a tag to compare

Patch Changes

@shopify/[email protected]

22 Mar 17:47
3c732da
Compare
Choose a tag to compare

Patch Changes

[email protected]

08 Mar 16:45
1d598b5
Compare
Choose a tag to compare

Changelog

0.11.0 - 2022-02-24

  • No updates. Transitive dependency bump.

0.10.0 - 2022-01-25

  • No updates. Transitive dependency bump.

0.9.0 - 2022-01-20

  • No updates. Transitive dependency bump.

0.8.0 - 2021-12-07

  • No updates. Transitive dependency bump.

0.7.1 - 2021-12-02

  • No updates. Transitive dependency bump.

0.7.0 - 2021-11-22

  • New rule hydrogen/no-effect-in-server-components. This rule prevents using useEffect and useLayoutEffect in non-client components.

0.6.2 - 2021-11-10

  • Added new hydrogen/typescript config
  • Added env#node: true and parserOptions#sourceType: 'module' to core config
  • Fixed issue requiring typescript to be install on non-typescript projects

0.6.0 - 2021-11-05

  • No updates. Transitive dependency bump.

0.5.0 - 2021-11-01

  • No updates. Transitive dependency bump.

0.4.0 - 2021-10-27

  • No updates. Transitive dependency bump.

0.3.0 - 2021-10-20

  • No updates. Transitive dependency bump.

0.2.1 - 2021-10-12

  • No updates. Transitive dependency bump.

0.2.0 - 2021-10-08

  • No updates. Transitive dependency bump.

0.1.3 - 2021-10-04

  • New rule hydrogen/prefer-image-component

0.1.2 - 2021-09-30

  • Added recommended-typescript config for typescript projects

0.1.0 - 2021-09-23

  • No updates. Transitive dependency bump.

1.0.0-alpha.22 - 2021-09-22

  • No updates. Transitive dependency bump.

[email protected]

08 Mar 16:45
1d598b5
Compare
Choose a tag to compare

Minor Changes

  • #858 eae3490 Thanks @michenly! - Upgrade default Storefront API to version '2022-04'. Some components have been updated to use the 2022-04 features and types as well.

    One important change is that the 2022-04 Storefront API no longer encodes object IDs: see more details here. Because of this, Hydrogen will no longer decode IDs, either, which will cause issues if you are using a previous version of the Storefront API with Hydrogen components.

  • #858 eae3490 Thanks @michenly! - Adds queryShop helper to API routes. This makes it easy to query the Storefront API, similar to how useShopQuery is available in server components:

    // my-api.server.js
    
    export default function api(request, {queryShop}) {
      return await queryShop({
        query: `query ShopName { shop { name } }`,
      });
    }

    queryShop accepts a single argument object with the following properties:

    Property Type Required
    query string | ASTNode Yes
    variables Record<string, any> No
    locale string (defaults to defaultLocale) No

    Important: In order to use queryShop, you should pass shopifyConfig to renderHydrogen inside App.server.jsx:

    -export default renderHydrogen(App, {routes});
    +export default renderHydrogen(App, {shopifyConfig, routes});
  • #858 eae3490 Thanks @michenly! - Routing in Hydrogen has been updated according to Custom Routes proposal. Specifically, a new Router component has been added, and DefaultRoutes has been renamed to FileRoutes, along with other minor changes. Custom route components are not implemented yet.

    Follow these steps to upgrade your App.server.jsx file:

    1. Rename the parameter pages to routes when calling renderHydrogen.
    2. Rename the DefaultRoutes component to FileRoutes.
    3. Add the new Router component as a parent of FileRoutes and pass fallback and serverProps props (previously in DefaultRoutes).
    4. Rename src/pages directory to src/routes and update the glob import in App.server.jsx to import.meta.globEager('./routes/**/*.server.[jt](s|sx)').

    Full example of App.server.jsx

    import renderHydrogen from '@shopify/hydrogen/entry-server';
    import {Router, FileRoutes, ShopifyProvider} from '@shopify/hydrogen';
    import {Suspense} from 'react';
    import shopifyConfig from '../shopify.config';
    import DefaultSeo from './components/DefaultSeo.server';
    import NotFound from './components/NotFound.server';
    import LoadingFallback from './components/LoadingFallback';
    import CartProvider from './components/CartProvider.client';
    
    function App({routes, ...serverProps}) {
      return (
        <Suspense fallback={<LoadingFallback />}>
          <ShopifyProvider shopifyConfig={shopifyConfig}>
            <CartProvider>
              <DefaultSeo />
              <Router fallback={<NotFound />} serverProps={serverProps}>
                <FileRoutes routes={routes} />
              </Router>
            </CartProvider>
          </ShopifyProvider>
        </Suspense>
      );
    }
    
    const routes = import.meta.globEager('./routes/**/*.server.[jt](s|sx)');
    export default renderHydrogen(App, {shopifyConfig, routes});

Patch Changes

  • #858 eae3490 Thanks @michenly! - Export Seo components Fragement and use them in the starter template.

  • #852 6015edf Thanks @frandiox! - Update @headlessui/react version to fix Cart dialog not opening.

@shopify/[email protected]

08 Mar 16:45
1d598b5
Compare
Choose a tag to compare

Minor Changes

  • #858 eae3490 Thanks @michenly! - Export Seo components Fragement and use them in the starter template.

  • #858 eae3490 Thanks @michenly! - Move any static Fragment properties on components to the entry point @shopify/hydrogen/fragments.
    The migration diff are as follows:

    - import {ExternalVideoFragment} from '@shopify/hydrogen';
    + import {ExternalVideoFragment} from '@shopify/hydrogen/fragments';
    - import type {ExternalVideoFragmentFragment} from '@shopify/hydrogen';
    + import type {ExternalVideoFragmentFragment} from '@shopify/hydrogen/fragments';
    - import {ImageFragment} from '@shopify/hydrogen';
    + import {ImageFragment} from '@shopify/hydrogen/fragments';
    - import type {ImageFragmentFragment} from '@shopify/hydrogen';
    + import type {ImageFragmentFragment} from '@shopify/hydrogen/fragments';
    - import {MediaFileFragment} from '@shopify/hydrogen';
    + import {MediaFileFragment} from '@shopify/hydrogen/fragments';
    - import type {MediaFileFragmentFragment} from '@shopify/hydrogen';
    + import type {MediaFileFragmentFragment} from '@shopify/hydrogen/fragments';
    - import {MetafieldFragment} from '@shopify/hydrogen';
    + import {MetafieldFragment} from '@shopify/hydrogen/fragments';
    - import type {MetafieldFragmentFragment} from '@shopify/hydrogen';
    + import type {MetafieldFragmentFragment} from '@shopify/hydrogen/fragments';
    - import {Model3DFragment} from '@shopify/hydrogen';
    + import {Model3DFragment} from '@shopify/hydrogen/fragments';
    - import type {Model3DFragmentFragment} from '@shopify/hydrogen';
    + import type {Model3DFragmentFragment} from '@shopify/hydrogen/fragments';
    - import {MoneyFragment} from '@shopify/hydrogen';
    + import {MoneyFragment} from '@shopify/hydrogen/fragments';
    - import type {MoneyFragmentFragment} from '@shopify/hydrogen';
    + import type {MoneyFragmentFragment} from '@shopify/hydrogen/fragments';
    - import {ProductProviderFragment} from '@shopify/hydrogen';
    + import {ProductProviderFragment} from '@shopify/hydrogen/fragments';
    - import type {ProductProviderFragmentFragment} from '@shopify/hydrogen';
    + import type {ProductProviderFragmentFragment} from '@shopify/hydrogen/fragments';
    - import {UnitPriceFragment} from '@shopify/hydrogen';
    + import {UnitPriceFragment} from '@shopify/hydrogen/fragments';
    - import type {UnitPriceFragmentFragment} from '@shopify/hydrogen';
    + import type {UnitPriceFragmentFragment} from '@shopify/hydrogen/fragments';
    - import {VideoFragment} from '@shopify/hydrogen';
    + import {VideoFragment} from '@shopify/hydrogen/fragments';
    - import type {VideoFragmentFragment} from '@shopify/hydrogen';
    + import type {VideoFragmentFragment} from '@shopify/hydrogen/fragments';
  • #858 eae3490 Thanks @michenly! - Updated the ExternalVideo component to use the new embedUrl Storefront API (introduced in 2022-04) on ExternalVideo.

  • #858 eae3490 Thanks @michenly! - Upgrade default Storefront API to version '2022-04'. Some components have been updated to use the 2022-04 features and types as well.

    One important change is that the 2022-04 Storefront API no longer encodes object IDs: see more details here. Because of this, Hydrogen will no longer decode IDs, either, which will cause issues if you are using a previous version of the Storefront API with Hydrogen components.

  • #858 eae3490 Thanks @michenly! - Adds queryShop helper to API routes. This makes it easy to query the Storefront API, similar to how useShopQuery is available in server components:

    // my-api.server.js
    
    export default function api(request, {queryShop}) {
      return await queryShop({
        query: `query ShopName { shop { name } }`,
      });
    }

    queryShop accepts a single argument object with the following properties:

    Property Type Required
    query string | ASTNode Yes
    variables Record<string, any> No
    locale string (defaults to defaultLocale) No

    Important: In order to use queryShop, you should pass shopifyConfig to renderHydrogen inside App.server.jsx:

    -export default renderHydrogen(App, {routes});
    +export default renderHydrogen(App, {shopifyConfig, routes});
  • #858 eae3490 Thanks @michenly! - Routing in Hydrogen has been updated according to Custom Routes proposal. Specifically, a new Router component has been added, and DefaultRoutes has been renamed to FileRoutes, along with other minor changes. Custom route components are not implemented yet.

    Follow these steps to upgrade your App.server.jsx file:

    1. Rename the parameter pages to routes when calling renderHydrogen.
    2. Rename the DefaultRoutes component to FileRoutes.
    3. Add the new Router component as a parent of FileRoutes and pass fallback and serverProps props (previously in DefaultRoutes).
    4. Rename src/pages directory to src/routes and update the glob import in App.server.jsx to import.meta.globEager('./routes/**/*.server.[jt](s|sx)').

    Full example of App.server.jsx

    import renderHydrogen from '@shopify/hydrogen/entry-server';
    import {Router, FileRoutes, ShopifyProvider} from '@shopify/hydrogen';
    import {Suspense} from 'react';
    import shopifyConfig from '../shopify.config';
    import DefaultSeo from './components/DefaultSeo.server';
    import NotFound from './components/NotFound.server';
    import LoadingFallback from './components/LoadingFallback';
    import CartProvider from './components/CartProvider.client';
    
    function App({routes, ...serverProps}) {
      return (
        <Suspense fallback={<LoadingFallback />}>
          <ShopifyProvider shopifyConfig={shopifyConfig}>
            <CartProvider>
              <DefaultSeo />
              <Router fallback={<NotFound />} serverProps={serverProps}>
                <FileRoutes routes={routes} />
              </Router>
            </CartProvider>
          </ShopifyProvider>
        </Suspense>
      );
    }
    
    const routes = import.meta.globEager('./routes/**/*.server.[jt](s|sx)');
    export default renderHydrogen(App, {shopifyConfig, routes});

Patch Changes

  • #858 eae3490 Thanks @michenly! - Update linesAdd to create cart if cart does not exist.

  • #858 eae3490 Thanks @michenly! - Hydrogen docs: Static assets and component props

  • #858 eae3490 Thanks @michenly! - Do not scroll to top if the URL pathname has not changed.

  • #858 eae3490 Thanks @michenly! - Add null check for ShopifyProvider

  • #858 eae3490 Thanks @michenly! - Ignore when boomerang doesn't load. This often happens when a adblocker is present on the client.
    There is no longer an uncaught promise exception in the console.

  • #858 eae3490 Thanks @michenly! - Avoid accessing undefined global __flight as a side effect of another unknown error.

  • #858 eae3490 Thanks @michenly! - Disable worker streaming until it is properly supported.

  • #858 [`eae349...

Read more

@shopify/[email protected]

08 Mar 16:45
1d598b5
Compare
Choose a tag to compare

Minor Changes

  • #858 eae3490 Thanks @michenly! - Upgrade default Storefront API to version '2022-04'. Some components have been updated to use the 2022-04 features and types as well.

    One important change is that the 2022-04 Storefront API no longer encodes object IDs: see more details here. Because of this, Hydrogen will no longer decode IDs, either, which will cause issues if you are using a previous version of the Storefront API with Hydrogen components.

v0.11.1

01 Mar 19:59
Compare
Choose a tag to compare

What's Changed

Full Changelog: Shopify/hydrogen@v0.11.0...v0.11.1

v0.11.0

24 Feb 17:34
57d5e40
Compare
Choose a tag to compare

This is an important release that brings us closer to release candidate. Please read the migration guide carefully, as there are a number of breaking changes. You can also use this pull request to view the changes between a brand new app in version 0.10.1 and version 0.11.0.

Warning: There are many breaking changes involved in this release. If you have not yet invested much time in customizing a v0.10 Hydrogen app, we recommend starting from scratch with v0.11 by running npx create-hydrogen-app@latest or waiting until the Release Candidate is announced.

Breaking changes

Refer to migration guide on all the breaking changes.

What's Changed

Read more

v0.11.0-experimental.2

22 Feb 22:20
Compare
Choose a tag to compare
Pre-release

This is an important release that brings us closer to release candidate. Please read the migration guide carefully, as there are a number of breaking changes. You can also use this pull request to view the changes between a brand new app in version 0.10.1 and version 0.11.0.

Warning: There are many breaking changes involved in this release. If you have not yet invested much time in customizing a v0.10 Hydrogen app, we recommend starting from scratch with v0.11 by running npx create-hydrogen-app@latest or waiting until the Release Candidate is announced.

Breaking changes

shopify.config.js

Hydrogen now implements the 2022-01 version of the Storefront API. Update your shopify.config.js file to use the 2022-01 storefrontApiVersion instead of unstable.

<ShopifyProvider>

Our 0.10 release removed <ShopifyProvider>. This was necessary because React Server Components do not currently support Context. That change also meant that you could only have a single Shopify configuration for your app. The config was global. After making this change, we received feedback, internally and externally, that there is value in being able to dynamically define the configuration per request. This is useful to aggregate multiple storefronts with a single Hydrogen app.

Because of these requests, we are bringing <ShopifyProvider> back. The challenge is that context is still not supported in React Server Components. Because of this, the new <ShopifyProvider> is special with a few shortcomings:

  1. You cannot have multiple instances of <ShopifyProvider> within your app. Because it is not using real context, all <ShopifyProvider> instances share the same configuration per request.
  2. You are still able to dynamically define the shopifyConfig prop, and it will remain isolated per request to the server, being thread safe.

Again, you cannot yet use context within your server components. We are working with Meta and hope to have a long term server context solution soon.

Migrate from Hydrogen version 0.10.0

  1. Remove shopifyConfig from both entry-client.jsx and entry-server.jsx.
  2. Add ShopifyProvider and shopifyConfig to App.server.jsx:
- import {DefaultRoutes} from '@shopify/hydrogen';
+ import {DefaultRoutes, ShopifyProvider} from '@shopify/hydrogen';
  import {Suspense} from 'react';

+ import shopifyConfig from '../shopify.config';
  import DefaultSeo from './components/DefaultSeo.server';
  import NotFound from './components/NotFound.server';
  import AppClient from './App.client';
  import LoadingFallback from './components/LoadingFallback';
  import {ShopifyProvider} from '@shopify/hydrogen';

  export default function App({log, pages, ...serverState}) {
    return (
      <Suspense fallback={<LoadingFallback />}>
+      <ShopifyProvider shopifyConfig={shopifyConfig}>
          <AppClient helmetContext={serverState.helmetContext}>
            <DefaultSeo />
            <DefaultRoutes
              pages={pages}
              serverState={serverState}
              log={log}
              fallback={<NotFound />}
            />
          </AppClient>
+      </ShopifyProvider>
      </Suspense>
    );
  }

React Router is completely gone

In version 0.10, we removed React Router on the server. With this release, we have removed React Router on the client as well. In most scenarios this shouldn't be a breaking change, unless you directly use React Router hooks or components within your client components. Simply remove react-router-dom from your package.json dependencies. Hydrogen exposes the following utilities for routing:

  1. <Link> component
  2. useNavigate hook
  3. useUrl hook

In a later release, we'll continue to enhance the routing capabilities in Hydrogen. Read more in the Custom Routes RFC.

Renamed Model3D to ModelViewer

The <Model3D /> component has now been renamed to <ModelViewer />.

Standalone Cart hooks removed

The following Cart hooks were removed because the same functionality can be obtained through the useCart hook:

  • useCartAttributesUpdateCallback
  • useCartBuyerIdentityUpdateCallback
  • useCartCheckoutUrl
  • useCartCreateCallback
  • useCartDiscountCodesUpdateCallback
  • useCartLinesAddCallback
  • useCartLinesRemoveCallback
  • useCartLinesTotalQuantity
  • useCartLinesUpdateCallback
  • useCartNoteUpdateCallback

Example

- import {useCartCheckoutUrl} from '@shopify/hydrogen'
+ import {useCart} from '@shopify/hydrogen'

- const checkoutUrl = useCartCheckoutUrl()
+ const {checkoutUrl} = useCart()

Render props removed

The following components no longer allow the function-as-a-child (also known as "render props") pattern; see #589.

Example

-import {Money} from '@shopify/hydrogen/client';
+import {useMoney} from '@shopify/hydrogen/client';

export default function MoneyCompareAtPrice({money}) {
+ const {amount, currencyNarrowSymbol} = useMoney(money);
  return (
-   <Money money={money}>
-     {({amount, currencyNarrowSymbol}) => (
       <span className="line-through text-lg mr-2.5 text-gray-500">
         {currencyNarrowSymbol}
         {amount}
       </span>
-     )}
-   </Money>
  );
}

Product and Cart component aliases removed

The following aliases have been removed. Use each component's original name:

Read more