- Updated dependencies [
2039a4a
,82b6af7
,361879e
]:- @shopify/[email protected]
- @shopify/[email protected]
-
Fix scroll issues on Product Detail Page for small screens (#782) by @lifeiscontent
-
Fix Layout title on mobile when title is long (#781) by @lifeiscontent
-
Adopt Remix
v2_meta
future flag (#738) by @wizardlyhel-
For any routes that you used
meta
route export, convert it to theV2_MetaFunction
equivalent. Notice that the package name in the import statement has also changed to'@remix-run/react'
:- import {type MetaFunction} from '@shopify/remix-oxygen'; + import {type V2_MetaFunction} from '@remix-run/react'; - export const meta: MetaFunction = () => { + export const meta: V2_MetaFunction = () => { - return {title: 'Login'}; + return [{title: 'Login'}]; };
-
If you are using data from loaders, pass the loader type to the
V2_MetaFunction
generic:- export const meta: MetaFunction = ({data}) => { + export const meta: V2_MetaFunction<typeof loader> = ({data}) => { - return {title: `Order ${data?.order?.name}`}; + return [{title: `Order ${data?.order?.name}`}]; };
-
If you are using
meta
route export inroot
, convert it to Global Meta// app/root.tsx - export const meta: MetaFunction = () => ({ - charset: 'utf-8', - viewport: 'width=device-width,initial-scale=1', - }); export default function App() { return ( <html lang={locale.language}> <head> + <meta charSet="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> <Seo /> <Meta />
-
-
Adopt
v2_routeConvention
future flag (#747) by @wizardlyhelRemix v2 route conventions are just file renames. We just need to ensure when changing file name and file location, the import paths of other files are also updated.
Go to Remix docs for more details on the V2 route convention.
Rename and move the following files in the
routes
folder to adopt to V2 route convention.Before After (V2 route convention) app/routes/ ├─ [sitemap.xml].tsx ├─ [robots.txt].tsx └─ ($lang)/ ├─ $shopid/orders/$token/ │ └─ authenticate.tsx ├─ account/ │ ├─ __private/ │ │ ├─ address/ │ │ │ └─ $id.tsx │ │ ├─ orders.$id.tsx │ │ ├─ edit.tsx │ │ └─ logout.ts │ └─ __public/ │ ├─ recover.tsx │ ├─ login.tsx │ ├─ register.tsx │ ├─ activate.$id.$activationToken.tsx │ └─ reset.$id.$resetToken.tsx ├─ api/ │ ├─ countries.tsx │ └─ products.tsx ├─ collections/ │ ├─ index.tsx │ ├─ $collectionHandle.tsx │ └─ all.tsx ├─ journal/ │ ├─ index.tsx │ └─ $journalHandle.tsx ├─ pages │ └─ $pageHandle.tsx ├─ policies/ │ ├─ index.tsx │ └─ $policyHandle.tsx ├─ products/ │ ├─ index.tsx │ └─ $productHandle.tsx ├─ $.tsx ├─ account.tsx ├─ cart.tsx ├─ cart.$lines.tsx ├─ discount.$code.tsx ├─ featured-products.tsx ├─ index.tsx └─ search.tsx
app/routes/ ├─ [sitemap.xml].tsx ├─ [robots.txt].tsx ├─ ($lang).$shopid.orders.$token.authenticate.tsx ├─ ($lang).account.address.$id.tsx ├─ ($lang).account.orders.$id.tsx ├─ ($lang).account.edit.tsx ├─ ($lang).account.logout.ts ├─ ($lang).account.recover.tsx ├─ ($lang).account.login.tsx ├─ ($lang).account.register.tsx ├─ ($lang).account.activate.$id.$activationToken.tsx ├─ ($lang).account.reset.$id.$resetToken.tsx ├─ ($lang).api.countries.tsx ├─ ($lang).api.products.tsx ├─ ($lang).collections._index.tsx ├─ ($lang).collections.$collectionHandle.tsx ├─ ($lang).collections.all.tsx ├─ ($lang).journal._index.tsx ├─ ($lang).journal.$journalHandle.tsx ├─ ($lang).pages.$pageHandle.tsx ├─ ($lang).policies._index.tsx ├─ ($lang).policies.$policyHandle.tsx ├─ ($lang).products._index.tsx ├─ ($lang).products.$productHandle.tsx ├─ $.tsx ├─ ($lang)._index.tsx ├─ ($lang).account.tsx ├─ ($lang).cart.tsx ├─ ($lang).cart.$lines.tsx ├─ ($lang).discount.$code.tsx ├─ ($lang).featured-products.tsx └─ ($lang).search.tsx
If you want to continue using nested folder routes but have the
v2_routeConvention
flag turned on, you may consider using the npm package@remix-run/v1-route-convention
.If you like the flat route convention but still wants a hybrid style of nested route folder, you may consider using the npm package
remix-flat-routes
-
Adopt Remix
unstable_tailwind
andunstable_postcss
future flags for the Demo Store template. (#751) by @frandiox-
Move the file
<root>/styles/app.css
to<root>/app/styles/app.css
, and remove it from.gitignore
. -
Add
"browserslist": ["defaults"]
to yourpackage.json
, or your preferred value from Browserslist. -
Replace the
build
anddev
scripts in yourpackage.json
with the following:Before
"scripts": { "build": "npm run build:css && shopify hydrogen build", "build:css": "postcss styles --base styles --dir app/styles --env production", "dev": "npm run build:css && concurrently -g --kill-others-on-fail -r npm:dev:css \"shopify hydrogen dev\"", "dev:css": "postcss styles --base styles --dir app/styles -w", ... }
After
"scripts": { "dev": "shopify hydrogen dev", "build": "shopify hydrogen build", ... }
You can also remove dependencies like
concurrently
if you don't use them anywhere else. -
-
Forwards search params of
/discount/<code>
route to a redirect route. (#766) by @lneicelis -
Carts created in liquid will soon be compatible with the Storefront API and vice versa, making it possible to share carts between channels. (#721) by @scottdixon
This change updates the Demo Store to use Online Store's
cart
cookie (instead of sessions) which prevents customers from losing carts when merchants migrate to/from Hydrogen. -
Bump internal Remix dependencies to 1.15.0. (#728) by @wizardlyhel
Recommendations to follow:
- Upgrade all the Remix packages in your app to 1.15.0.
- Enable Remix v2 future flags at your earliest convenience following the official guide.
-
Updated CLI prompts. It's recommended to update your version of
@shopify/cli
to3.45.0
when updating@shopify/cli-hydrogen
. (#733) by @frandiox"dependencies": { - "@shopify/cli": "3.x.x", + "@shopify/cli": "3.45.0", }
-
Adopt Remix
v2_errorBoundary
future flag (#729) by @wizardlyhel-
Remove all
CatchBoundary
route exports -
Handle route level errors with
ErrorBoundary
Before:
// app/root.tsx export function ErrorBoundary({error}: {error: Error}) { const [root] = useMatches(); const locale = root?.data?.selectedLocale ?? DEFAULT_LOCALE; return ( <html lang={locale.language}> <head> <title>Error</title> <Meta /> <Links /> </head> <body> <Layout layout={root?.data?.layout}> <GenericError error={error} /> </Layout> <Scripts /> </body> </html> ); }
After:
// app/root.tsx import {isRouteErrorResponse, useRouteError} from '@remix-run/react'; export function ErrorBoundary({error}: {error: Error}) { const [root] = useMatches(); const locale = root?.data?.selectedLocale ?? DEFAULT_LOCALE; const routeError = useRouteError(); const isRouteError = isRouteErrorResponse(routeError); let title = 'Error'; let pageType = 'page'; // We have an route error if (isRouteError) { title = 'Not found'; // We have a page not found error if (routeError.status === 404) { pageType = routeError.data || pageType; } } return ( <html lang={locale.language}> <head> <title>{title}</title> <Meta /> <Links /> </head> <body> <Layout layout={root?.data?.layout} key={`${locale.language}-${locale.country}`} > {isRouteError ? ( <> {routeError.status === 404 ? ( <NotFound type={pageType} /> ) : ( <GenericError error={{ message: `${routeError.status} ${routeError.data}`, }} /> )} </> ) : ( <GenericError error={error instanceof Error ? error : undefined} /> )} </Layout> <Scripts /> </body> </html> ); }
-
-
Updated dependencies [
e6e6c2d
,475a39c
,1f8526c
,0f4d562
,737f83e
,2d4c5d9
,68a6028
]:- @shopify/[email protected]
- @shopify/[email protected]
- @shopify/[email protected]