Releases: Shopify/hydrogen-v1
[email protected]
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 theyarn 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 yourpackage.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 ofvite
.To update your existing apps, install the Shopify & Hydrogen CLIs:
yarn add -D @shopify/cli @shopify/cli-hydrogen
And update the
dev
script in yourpackage.json
:- "dev": "vite", + "dev": "shopify hydrogen dev",
@shopify/[email protected]
Patch Changes
-
#1082
bd14340c
Thanks @jplhomer! - UpdateuseUrl()
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]
Minor Changes
-
#983
52af261b
Thanks @jplhomer! - Introduce Suspense-friendlyfetchSync
API for server and client components.When using
fetchSync
in server components, you provide options for caching and preloading. This is similar to theuseQuery
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 importfetchSync
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 headerstale-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]
Minor Changes
-
#1028
ba174588
Thanks @michenly! - Starting from SF API version2022-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. Thelocale
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 thelanguageCode
key, which is the first two characters of the existinglocale
key.Both
locale
&languageCode
values are also now capitalized to make it easier to pass into a GraphQL@inContext
directive. -
#1020
e9529bc8
Thanks @jplhomer! - PreloadLink
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]
Minor Changes
-
#1028
ba174588
Thanks @michenly! - Starting from SF API version2022-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. Thelocale
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 thelanguageCode
key, which is the first two characters of the existinglocale
key.Both
locale
&languageCode
values are also now capitalized to make it easier to pass into a GraphQL@inContext
directive. -
#1020
e9529bc8
Thanks @jplhomer! - PreloadLink
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). -
#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 skipedges
and go directly tonode
, for example:product.nodes[0]
instead ofproduct.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]
Patch Changes
- #999
66cc632a
Thanks @cartogram! - Fixes the rule:server-component-banned-hooks
to allow the banned hooks in shared components.
@shopify/[email protected]
@shopify/[email protected]
Patch Changes
-
#1008
ca1de82b
Thanks @frandiox! - Allow passingcache
parameter tocreateServer
in Node entry. -
#997
fffdc08f
Thanks @frandiox! - Allow empty array values in flattenConnection utility. -
#1007
7cfca7b0
Thanks @scottdixon! - Fix API index routes https://github.com/Shopify/hydrogen/issues/1006 -
#1000
6d0d5068
Thanks @frandiox! - Do not cache Storefront API responses that contain GraphQL errors. -
#1003
d8a9c929
Thanks @jplhomer! - Update useShopQuery to accept a custom Storefront API secret token, and forward the Buyer IP.
[email protected]
Minor Changes
- #877
a362a5dd
Thanks @cartogram! - Breaking Change: New rulesclient-component-banned-hooks
andserver-component-banned-hooks
added as generic rules to ban any non-supported hooks in each context.server-component-banned-hooks
combines and replaces theno-state-in-server-components
andno-effects-in-server-components
rules.client-component-banned-hooks
will flag usage ofuseQuery
anduseShopQuery
in client components.
[email protected]
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 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
-
#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
-
#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:
- 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.
-
#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 [email protected] [email protected]
-
#917
be888259
Thanks @jplhomer! - Add accessible button label for mobile navigation -
[#918](htt...