@shopify/hydrogen@0.13.0
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 theLocalizationProvider
. As a result, theuseAvailableCountries
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 aStyleTag
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>
ComponentThe
<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 takesfallback
as a prop. It also doesn't needserverProps
. 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 thansrc/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()
hookYou 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 theRawhtml
component.Upgrade your project by replacing references to the
RawHtml
component to follow
React'sdangerouslySetInnerHTML
: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:
- When an app directly loads the redirect route, the server will render a 300 redirect with the proper location header.
- 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 version0.0.0-experimental-2bf7c02f0-20220314
.To upgrade your Hydrogen app, change the pinned version of
react
andreact-dom
in yourpackage.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 aRequest
argument. Instead, it now accepts aurl: string
andoptions: 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