Skip to content

Releases: Shopify/hydrogen-v1

[email protected]

19 Apr 17:58
e8a79d6
Compare
Choose a tag to compare

Minor Changes

Patch Changes

  • #929 f9e76eb7 Thanks @cartogram! - Deprecate @shopify/hydrogen-cli. Use Shopify CLI (@shopify/cli-hydrogen instead.

    The template now adds the @shopify/cli dependencies for the yarn preview command. To update your existing app:

    To update your existing apps, install the Shopify & Hydrogen CLIs:

    yarn add -D @shopify/cli @shopify/cli-hydrogen

    And update the preview script in your package.json:

    -    "preview": "npx @shopify/hydrogen-cli@latest preview",
    +    "preview": "shopify hydrogen preview",
  • #1089 3c189665 Thanks @cartogram! - Use Shopify CLI to start a local development server instead of vite.

    To update your existing apps, install the Shopify & Hydrogen CLIs:

    yarn add -D @shopify/cli @shopify/cli-hydrogen

    And update the dev script in your package.json:

    -    "dev": "vite",
    +    "dev": "shopify hydrogen dev",

@shopify/[email protected]

19 Apr 17:58
e8a79d6
Compare
Choose a tag to compare

Patch Changes

  • #1082 bd14340c Thanks @jplhomer! - Update useUrl() to allow a developer to subscribe to a reactive version of the current router location.

    Example:

    import {useUrl} from '@shopify/hydrogen/client';
    
    function MyClientComponent() {
      const url = useUrl();
    
      useEffect(() => {
        // Record navigation, analytics, etc
      }, [url]);
    }
  • #1075 05dea552 Thanks @jplhomer! - Properly set buyer IP and secret token for API Route queryShop helper

@shopify/[email protected]

13 Apr 15:34
3ca0685
Compare
Choose a tag to compare

Minor Changes

  • #983 52af261b Thanks @jplhomer! - Introduce Suspense-friendly fetchSync API for server and client components.

    When using fetchSync in server components, you provide options for caching and preloading. This is similar to the useQuery hook:

    import {fetchSync, CacheMinutes} from '@shopify/hydrogen';
    import {Suspense} from 'react';
    
    export function MyServerComponent() {
      return (
        <Suspense fallback="Loading...">
          <MyThings />
        </Suspense>
      );
    }
    
    function MyThings() {
      const things = fetchSync('https://3p.api.com/things.json', {
        preload: true,
        cache: CacheMinutes(),
      }).json();
    
      return <h2>{things.title}</h2>;
    }

    When using fetchSync in client components, you cannot provide options for caching and preloading. You must import fetchSync from @shopify/hydrogen/client:

    import {fetchSync} from '@shopify/hydrogen/client';
    import {Suspense} from 'react';
    
    export function MyClientComponent() {
      return (
        <Suspense fallback="Loading...">
          <MyThings />
        </Suspense>
      );
    }
    
    function MyThings() {
      const things = fetchSync('https://3p.api.com/things.json').json();
    
      return <h2>{things.title}</h2>;
    }
  • #890 a4c6d6c4 Thanks @wizardlyhel! - Analytics instrumentation - this provides integration points for both server
    and client side analytics instrumentations

Patch Changes

  • #1061 a4aa3887 Thanks @jplhomer! - Support script tags in index.html that contain line breaks

  • #1057 06d92ddc Thanks @frandiox! - Ability to concatenate requests in API route handlers without leaving the server by returning a new Request instance.

    // src/routes/my-page.server.jsx
    
    export async function api(request) {
      if (request.method === 'POST') {
        // do some work here...
      }
    
      return new Request(request.url, {method: 'GET'});
    }
    
    export default function Page() {
      return (
        <form action="/my-page" method="POST">
          ...
        </form>
      );
    }

    In the previous example, a POST request to /my-page would run the API handler and automatically continue with the server component rendering (GET). This is useful for handling HTML forms without waterfall requests.

  • #1049 b88a885d Thanks @wizardlyhel! - Support sub request cache control header stale-while-revalidate everywhere

  • #1047 5268bf85 Thanks @jplhomer! - Restore scroll position when navigating using the back and forward buttons.

  • #1062 cc172ae7 Thanks @jplhomer! - Fix encoding of quotes in CSS Modules which caused hydration errors

  • #1046 3947d53a Thanks @michenly! - Fixed server Cookie bug where initializing with empty string will resulted in 1 item in the Cookies Map.

  • #1059 401f329d Thanks @frandiox! - Fix link prefetch mismatch due to query-string

  • #1072 47c0c184 Thanks @michenly! - Improve type for ShopifyContextValue to be based on ShopifyConfig.

[email protected]

05 Apr 19:21
bbc8ad6
Compare
Choose a tag to compare

Minor Changes

  • #1028 ba174588 Thanks @michenly! - Starting from SF API version 2022-04, the preferred way to request translatable resources is using the @inContext directive. See the API docs on how to do this and which resources have translatable properties.

    This causes a breaking change to the useShopQuery hook. The locale property has been removed from the argument object; Accept-Language is no longer being send with every request, and we are no longer using locale as part of the cache key.

    The useShop hook will now return the languageCode key, which is the first two characters of the existing locale key.

    Both locale & languageCode values are also now capitalized to make it easier to pass into a GraphQL @inContext directive.

  • #1020 e9529bc8 Thanks @jplhomer! - Preload Link URLs by default when a user signals intent to visit the URL. This includes hovering or focusing on the URL. To disable preloading, pass <Link preload={false} /> to the component.

@shopify/[email protected]

05 Apr 19:21
bbc8ad6
Compare
Choose a tag to compare

Minor Changes

  • #1028 ba174588 Thanks @michenly! - Starting from SF API version 2022-04, the preferred way to request translatable resources is using the @inContext directive. See the API docs on how to do this and which resources have translatable properties.

    This causes a breaking change to the useShopQuery hook. The locale property has been removed from the argument object; Accept-Language is no longer being send with every request, and we are no longer using locale as part of the cache key.

    The useShop hook will now return the languageCode key, which is the first two characters of the existing locale key.

    Both locale & languageCode values are also now capitalized to make it easier to pass into a GraphQL @inContext directive.

  • #1020 e9529bc8 Thanks @jplhomer! - Preload Link URLs by default when a user signals intent to visit the URL. This includes hovering or focusing on the URL. To disable preloading, pass <Link preload={false} /> to the component.

Patch Changes

  • #1017 4c87fb63 Thanks @frandiox! - Do not cache Storefront API responses that contain GraphQL errors (amend previous fix).

  • #1039 3a297862 Thanks @frandiox! - Update to Vite 2.9

  • #1026 836b064d Thanks @frehner! - Updated the Typescript types and GraphQL schema to the newest updates from Storefront API 2022-04. Of note in this update is the ability to skip edges and go directly to node, for example: product.nodes[0] instead of product.edges[0].node

  • #1032 03488083 Thanks @jplhomer! - Catch hydration errors related to experimental server components bugs and prevent them from being logged in production.

  • #1037 13376efb Thanks @jplhomer! - Use new header for private Storefront token

[email protected]

29 Mar 14:30
64bb3ab
Compare
Choose a tag to compare

Patch Changes

  • #999 66cc632a Thanks @cartogram! - Fixes the rule: server-component-banned-hooks to allow the banned hooks in shared components.

@shopify/[email protected]

29 Mar 19:25
08b4a4a
Compare
Choose a tag to compare

Patch Changes

@shopify/[email protected]

29 Mar 14:30
64bb3ab
Compare
Choose a tag to compare

Patch Changes

[email protected]

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

Minor Changes

  • #877 a362a5dd Thanks @cartogram! - Breaking Change: New rules client-component-banned-hooks and server-component-banned-hooks added as generic rules to ban any non-supported hooks in each context. server-component-banned-hooks combines and replaces the no-state-in-server-components and no-effects-in-server-components rules. client-component-banned-hooks will flag usage of useQuery and useShopQuery in client components.

[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

  • #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
  • #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

  • #906 4db9534c Thanks @blittle! - Optimize the GraphQL query for the home page

  • #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.
  • #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 [email protected] [email protected]
  • #917 be888259 Thanks @jplhomer! - Add accessible button label for mobile navigation

  • [#918](htt...

Read more