Skip to content

@shopify/hydrogen@0.13.0

Compare
Choose a tag to compare
@github-actions github-actions released this 22 Mar 17:47
· 866 commits to v1.x-2022-07 since this release
3c732da

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 Thanks @wizardlyhel! - Removed the Rawhtml component.

    Upgrade your project by replacing references to the RawHtml component to follow
    React's dangerouslySetInnerHTML:

    Change all RawHtml component

    <RawHtml string="<p>Hello world</p>" />

    to jsx equivalent

    <div dangerouslySetInnerHTML={{__html: '<p>Hello world</p>'}} />

Patch Changes

  • #870 4c0fcd8f Thanks @frandiox! - Remove useQuery hook from client exports to avoid leaking server logic to the browser.

  • #950 d19fc36b Thanks @frandiox! - Allow disabling minification in vite.config.js

  • #981 8dda8a86 Thanks @michenly! - Fix useUrl() when it is in RSC mode

  • #965 cdad13ed Thanks @blittle! - Fix server redirects to work properly with RSC responses. For example, the redirect component within the starter template needs to change:

    export default function Redirect({response}) {
    -  response.redirect('/products/snowboard');
    -  return <div>This page is redirected</div>;
    +  return response.redirect('/products/snowboard');
    }

    This server component is rendered two ways:

    1. When an app directly loads the redirect route, the server will render a 300 redirect with the proper location header.
    2. The app is already loaded, but the user navigates to the redirected route. We cannot 300 respond in this scenario, instead response.redirect(...) returns a component which will redirect on the client.
  • #904 1b46f8d0 Thanks @wizardlyhel! - Log query key when provided in string

  • #758 0bee3af0 Thanks @frandiox! - Upgrade to React experimental version 0.0.0-experimental-2bf7c02f0-20220314.

    To upgrade your Hydrogen app, change the pinned version of react and react-dom in your package.json file to this version, or run:

    yarn add @shopify/hydrogen react@0.0.0-experimental-2bf7c02f0-20220314 react-dom@0.0.0-experimental-2bf7c02f0-20220314
  • #895 1017b541 Thanks @frandiox! - Improve error thrown in development when entry point fails on load.

  • #897 c01044e6 Thanks @blittle! - Add new custom headers for storefront API calls. See Issue #660

  • #908 8f4cd100 Thanks @mcvinci! - Hydrogen docs: Updates to align with latest release

  • #871 4cb07c73 Thanks @scottdixon! - Hydrogen docs: Update ProductProvider example query

  • #878 587aa3e6 Thanks @frandiox! - Fix preloading queries in workers to prevent waterfall requests.

    Breaking change: fetchBuilder no longer accepts a Request argument. Instead, it now accepts a url: string and options: FetchInit:

    -fetchBuilder(new Request('https://my.endpoint.com', {headers: {foo: 'bar'}}));
    +fetchBuilder('https://my.endpoint.com', {headers: {foo: 'bar}});
  • #923 993be985 Thanks @frandiox! - Provide a Logger option to use GraphQL and disable by default. Improve logging of unused query properties.

  • #960 2e8a5ea2 Thanks @mcvinci! - Hydrogen docs: Add reference to robots.txt.server.js file