-
Hydrogen is now compatible with TypeScript v5. (#1240) by @frandiox
If you have
typescriptas a dev dependency in your app, it is recommended to change its version as follows:"devDependencies": { ... - "typescript": "^4.9.5", + "typescript": "^5.2.2", },After installing the new version of TypeScript, you may need to update the version used in your IDE. For example, in VSCode, you can do this by clicking on the
{ }icon in the bottom-right toolbar next to the language mode (generally,{ } TypeScript JSXwhen editing a.tsxfile). -
Updated dependencies [
3491fd5c,06516ee9,d67ce6aa,1b7e0016,ee6e2920,17892a72,1a7762bc,1f8acd7b]:- @shopify/cli-hydrogen@5.2.1
- @shopify/hydrogen@2023.7.4
-
Support Remix Hot Module Replacement (HMR) and Hot Data Revalidation (HDR). (#1187) by @frandiox
Start using it with the following changes to your project:
-
Upgrade to the latest Hydrogen version and Remix 1.19.1.
-
Enable the v2 dev server in
remix.config.js:
// ... future: { + v2_dev: true, v2_meta: true, v2_headers: true, // ... }- Add Remix'
<LiveReload />component if you don't have it to yourroot.jsxorroot.tsxfile:
import { Outlet, Scripts, + LiveReload, ScrollRestoration, } from '@remix-run/react'; // ... export default function App() { // ... return ( <html> <head> {/* ... */} </head> <body> <Outlet /> <ScrollRestoration /> <Scripts /> + <LiveReload /> </body> </html> ); } export function ErrorBoundary() { // ... return ( <html> <head> {/* ... */} </head> <body> Error! <Scripts /> + <LiveReload /> </body> </html> ); } -
-
Performance optimization on product page (#1256) by @wizardlyhel
-
Add shouldRevalidate export to limit root loaders revalidation on mutations only (#1237) by @juanpprieto
-
Updated dependencies [
a06b5093,d053978d,9fcfc500,ec21cfd6,867866d1,bdac4c22,d896c76b,46d5f8ff,632a7a38,e536ae04]:- @shopify/cli-hydrogen@5.2.0
- @shopify/hydrogen@2023.7.3
-
Update @shopify/oxygen-workers-types dependencies (#1208) by @juanpprieto
-
Fix demo-store analytics (#1177) by @wizardlyhel
-
Updated dependencies [
b29c85d0,21eb9dac]:- @shopify/hydrogen@2023.7.2
- @shopify/cli-hydrogen@5.1.2
- @shopify/remix-oxygen@1.1.3
-
It's recommended to update
@shopify/cli: (#1172) by @frandiox-"@shopify/cli": "3.47.5" +"@shopify/cli": "3.48.0"
Also, for projects using Remix v1 Error Boundary convention, remove the deprecated
ErrorBoundaryComponenttype (or update to the v2 convention):-export const ErrorBoundary: ErrorBoundaryComponent = ({error}) => { +export const ErrorBoundary = ({error}: {error: Error}) => {
-
Updated dependencies [
b7a8ecf6,ef809228,1015f170,076bab7d]:- @shopify/remix-oxygen@1.1.2
- @shopify/hydrogen@2023.7.1
- @shopify/cli-hydrogen@5.1.1
-
Add
.envfile to Remix watcher to allow reloading environment variables on file save. Inremix.config.js: (#997) by @frandiox-watchPaths: ['./public'], +watchPaths: ['./public', './.env'],
-
Function and component for cart management: (#786) by @wizardlyhel
createCartHandler- Creates an object instance that simplifies cart operations such as add/update/remove from cart.CartForm- A form component that helps you sets up form inputs for cart handler.
Documentation:
- Updated how-to guides
createCartHandlerCartForm
-
Fix demostore to check for
shop.primaryDomainhost for navigation menu items. (#1036) by @rista404 -
Fix empty discount code (#1104) by @wizardlyhel
-
Add a
<VariantSelector>component to make building product forms easier. Also addedgetFirstAvailableVariantandgetSelectedProductOptionshelper functions. See the proposal for examples. (#1027) by @blittle -
Add @total-typescript/ts-reset to demo-store and skeleton templates (#1042) by @juanpprieto
-
Updated dependencies [
4c0858f2,c39411e0,dc56d296,2a036d72,667ea4fb,ed9782bc,4bee03df,11ab64a8,9482bc59,31409877,00f3e592,4db61421,5530d987,63d17266,5530d987,1befd365,945fdc57]:- @shopify/hydrogen@2024.0.0
- @shopify/cli-hydrogen@6.0.0
-
Update Remix to the latest version (
1.17.1). (#852) by @frandioxWhen updating your app, remember to also update your Remix dependencies to
1.17.1in yourpackage.jsonfile:-"@remix-run/react": "1.15.0", +"@remix-run/react": "1.17.1", -"@remix-run/dev": "1.15.0", -"@remix-run/eslint-config": "1.15.0", +"@remix-run/dev": "1.17.1", +"@remix-run/eslint-config": "1.17.1",
-
Updated dependencies [
f29e178a]:- @shopify/remix-oxygen@1.1.1
- @shopify/hydrogen@2023.4.5
- @shopify/cli-hydrogen@5.0.1
-
A default
https://protocol is now added automatically tostoreDomainif missing. (#985) by @frandiox -
Start using GraphQL code generation. This allows us to have full-stack type-safety and better developer experience. (#937) by @frandiox
As a result of the above, we've fixed issues where the frontend was accessing data that was not correctly fetched from the Storefront API. For example, missing
product.vendoror accessingtotalPriceinstead oftotalPriceV2.To enable the unstable codegen feature in your project, run your dev command as
shopify hydrogen dev --codegen-unstable. See the changes associated here for examples. -
Update the demostore to not cache the customer query. This is important to update in your app if you copied the logic from the demo store. (#950) by @blittle
-
Remove wrong cache control headers from route. Demo store is setting
cache-controlheader when it is not suppose to. The demo store server renders cart information. Cart information is consider personalized content and should never be cached in any way. (#991) by @wizardlyhelRoute
($locale).api.countries.tsxcan have cache control header because it is an API endpoint that doesn't render the cart. -
Make
storefrontApiVersionparameter optional. By default, it will use the current version of Hydrogen as the Storefront API version. (#984) by @frandiox -
Updated dependencies [
b2195520,4c5cdfd6,7b4afea2,42683d0a,7d6a1a7c,808ceb51,442f602a,be912b2f,8ccf6dbe,428c78dc,93a7c3c6,5124d618]:- @shopify/cli-hydrogen@5.0.0
- @shopify/hydrogen@2023.4.4
- @shopify/remix-oxygen@1.1.0
-
Updated dependencies [
7aaa4e86]:- @shopify/cli-hydrogen@4.2.1
- @shopify/hydrogen@2023.4.3
- @shopify/remix-oxygen@1.0.7
-
Fix the load more results button on the /search route (#909) by @juanpprieto
-
Adds pagination support on /search results (#918) by @juanpprieto
-
Added import/order ESLint rule and @remix-run/eslint plugin to demo-store template eslint configuration. (#895) by @QuintonC
-
Updated dependencies [
1a9f4025,112ac42a,a8d5fefe,24b82fcf,3cc6d751,112ac42a,ba54a3b6]:- @shopify/cli-hydrogen@4.2.0
- @shopify/hydrogen@2023.4.2
- All routes were changed from having a
$langpath parameter to having a$localepath parameter. See #860 for more details. (#864) by @frehner
-
Add
.shopifyto the .gitignore file to support upcoming CLI changes (#784) by @graygilmore -
Move GraphQL fragments from the beginning of the template literal to the end of it, so that we don't get the EOF error in VSCode. (#833) by @frehner
-
Updated Tailwind configuration file with a new dynamic opacity placeholder for colors (#851) by @blanklob
-
Updated dependencies [
685bb696,025385b6,35a87107,33f33edd,0a009a3b,9c2e67c5,9c2e67c5,3d458e2b]:- @shopify/cli-hydrogen@4.1.2
- @shopify/remix-oxygen@1.0.6
- @shopify/hydrogen@2023.4.1
- Updated dependencies [
2039a4a,82b6af7,361879e]:- @shopify/cli-hydrogen@4.1.1
- @shopify/hydrogen@2023.4.0
-
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_metafuture flag (#738) by @wizardlyhel-
For any routes that you used
metaroute export, convert it to theV2_MetaFunctionequivalent. 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_MetaFunctiongeneric:- 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
metaroute 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_routeConventionfuture 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
routesfolder 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_routeConventionflag 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_tailwindandunstable_postcssfuture flags for the Demo Store template. (#751) by @frandiox-
Move the file
<root>/styles/app.cssto<root>/app/styles/app.css, and remove it from.gitignore. -
Add
"browserslist": ["defaults"]to yourpackage.json, or your preferred value from Browserslist. -
Replace the
buildanddevscripts in yourpackage.jsonwith 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
concurrentlyif 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
cartcookie (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/clito3.45.0when updating@shopify/cli-hydrogen. (#733) by @frandiox"dependencies": { - "@shopify/cli": "3.x.x", + "@shopify/cli": "3.45.0", } -
Adopt Remix
v2_errorBoundaryfuture flag (#729) by @wizardlyhel-
Remove all
CatchBoundaryroute exports -
Handle route level errors with
ErrorBoundaryBefore:
// 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/cli-hydrogen@4.1.0
- @shopify/hydrogen@2023.1.7
- @shopify/remix-oxygen@1.0.5