Skip to content

Commit

Permalink
Merge pull request #20 from Shopify/fd-2024-4
Browse files Browse the repository at this point in the history
Update to 2024.4
  • Loading branch information
frandiox authored Apr 12, 2024
2 parents 130a3b7 + be6b773 commit d12043d
Show file tree
Hide file tree
Showing 27 changed files with 1,001 additions and 1,218 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ PUBLIC_STOREFRONT_API_TOKEN=33ad0f277e864013b8e3c21d19432501
PUBLIC_STORE_DOMAIN=hydrogen-preview.myshopify.com
PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID=shp_3cecd990-4824-4e27-beb2-46c8e822ec14
PUBLIC_CUSTOMER_ACCOUNT_API_URL=https://shopify.com/55145660472
PUBLIC_CHECKOUT_DOMAIN=checkout.hydrogen.shop
249 changes: 249 additions & 0 deletions .hydrogen/upgrade-2024.1.4-to-2024.4.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
# Hydrogen upgrade guide: 2024.1.4 to 2024.4.0

---

## Features

### Add `@shopify/mini-oxygen` as a dev dependency for local development [#1891](https://github.com/Shopify/hydrogen/pull/1891)

#### package.json

[#1891](https://github.com/Shopify/hydrogen/pull/1891)

```diff
"devDependencies": {
"@remix-run/dev": "^2.8.0",
"@remix-run/eslint-config": "^2.8.0",
+ "@shopify/mini-oxygen": "^3.0.0",
"@shopify/oxygen-workers-types": "^4.0.0",
...
}
```

### Support scaffolding projects from external repositories using the `--template` flag [#1867](https://github.com/Shopify/hydrogen/pull/1867)

#### The following examples are equivalent

[#1867](https://github.com/Shopify/hydrogen/pull/1867)

```bash
npm create @shopify/hydrogen -- --template shopify/hydrogen-demo-store
npm create @shopify/hydrogen -- --template github.com/shopify/hydrogen-demo-store
npm create @shopify/hydrogen -- --template https://github.com/shopify/hydrogen-demo-store
```

### Deprecate the `<Seo />` component in favor of directly using Remix meta route exports [#1875](https://github.com/Shopify/hydrogen/pull/1875)

#### Step: 1. Remove the `<Seo />` component from `root.jsx` [#1875](https://github.com/Shopify/hydrogen/pull/1875)

[#1875](https://github.com/Shopify/hydrogen/pull/1875)

```diff
export default function App() {
const nonce = useNonce();
const data = useLoaderData<typeof loader>();

return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
- <Seo />
<Meta />
<Links />
</head>
<body>
<Layout {...data}>
<Outlet />
</Layout>
<ScrollRestoration nonce={nonce} />
<Scripts nonce={nonce} />
<LiveReload nonce={nonce} />
</body>
</html>
);
}
```

#### Step: 2. Add a Remix meta export to each route that returns an seo property from a loader or handle: [#1875](https://github.com/Shopify/hydrogen/pull/1875)

[#1875](https://github.com/Shopify/hydrogen/pull/1875)

```diff
+import {getSeoMeta} from '@shopify/hydrogen';

export async function loader({context}) {
const {shop} = await context.storefront.query(`
query layout {
shop {
name
description
}
}
`);

return {
seo: {
title: shop.title,
description: shop.description,
},
};
}

+export const meta = ({data}) => {
+ return getSeoMeta(data.seo);
+};
```

#### Step: 3. Merge root route meta data [#1875](https://github.com/Shopify/hydrogen/pull/1875)

[#1875](https://github.com/Shopify/hydrogen/pull/1875)
If your root route loader also returns an seo property, make sure to merge that data:

```js
export const meta = ({data, matches}) => {
return getSeoMeta(
matches[0].data.seo,
// the current route seo data overrides the root route data
data.seo,
);
};
```

Or more simply:

```js
export const meta = ({data, matches}) => {
return getSeoMeta(...matches.map((match) => match.data.seo));
};
```

#### Step: 4. Override meta [#1875](https://github.com/Shopify/hydrogen/pull/1875)

[#1875](https://github.com/Shopify/hydrogen/pull/1875)
Sometimes getSeoMeta might produce a property in a way you'd like to change. Map over the resulting array to change it. For example, Hydrogen removes query parameters from canonical URLs, add them back:

```js
export const meta = ({data, location}) => {
return getSeoMeta(data.seo).map((meta) => {
if (meta.rel === 'canonical') {
return {
...meta,
href: meta.href + location.search,
};
}

return meta;
});
};
```

### Codegen dependencies must be now listed explicitly in package.json [#1962](https://github.com/Shopify/hydrogen/pull/1962)

#### Update package.json

[#1962](https://github.com/Shopify/hydrogen/pull/1962)

```diff
{
"devDependencies": {
+ "@graphql-codegen/cli": "5.0.2",
"@remix-run/dev": "^2.8.0",
"@remix-run/eslint-config": "^2.8.0",
+ "@shopify/hydrogen-codegen": "^0.3.0",
"@shopify/mini-oxygen": "^2.2.5",
"@shopify/oxygen-workers-types": "^4.0.0",
...
}
}
```

---

---

## Fixes

### Fix a bug where cart could be null, even though a new cart was created by adding a line item. [#1865](https://github.com/Shopify/hydrogen/pull/1865)

#### Example

[#1865](https://github.com/Shopify/hydrogen/pull/1865)

```ts
import {
createCartHandler,
cartGetIdDefault,
cartSetIdDefault,
} from '@shopify/hydrogen';

const cartHandler = createCartHandler({
storefront,
getCartId: cartGetIdDefault(request.headers),
setCartId: cartSetIdDefault(),
cartQueryFragment: CART_QUERY_FRAGMENT,
cartMutateFragment: CART_MUTATE_FRAGMENT,
});

await cartHandler.addLines([{merchandiseId: '...'}]);
// .get() now returns the cart as expected
const cart = await cartHandler.get();
```

### Update Vite plugin imports, and how their options are passed to Remix [#1935](https://github.com/Shopify/hydrogen/pull/1935)

#### vite.config.js

[#1935](https://github.com/Shopify/hydrogen/pull/1935)

```diff
-import {hydrogen, oxygen} from '@shopify/cli-hydrogen/experimental-vite';
+import {hydrogen} from '@shopify/hydrogen/vite';
+import {oxygen} from '@shopify/mini-oxygen/vite';
import {vitePlugin as remix} from '@remix-run/dev';

export default defineConfig({
hydrogen(),
oxygen(),
remix({
- buildDirectory: 'dist',
+ presets: [hydrogen.preset()],
future: {
```

### Change `storefrontRedirect` to ignore query parameters when matching redirects [#1900](https://github.com/Shopify/hydrogen/pull/1900)

#### This is a breaking change. If you want to retain the legacy functionality that is query parameter sensitive, pass matchQueryParams to storefrontRedirect():

[#1900](https://github.com/Shopify/hydrogen/pull/1900)

```js
storefrontRedirect({
request,
response,
storefront,
+ matchQueryParams: true,
});
```

### Fix types returned by the session object [#1869](https://github.com/Shopify/hydrogen/pull/1869)

#### In remix.env.d.ts or env.d.ts, add the following types

[#1869](https://github.com/Shopify/hydrogen/pull/1869)

```diff
import type {
// ...
HydrogenCart,
+ HydrogenSessionData,
} from '@shopify/hydrogen';

// ...

declare module '@shopify/remix-oxygen' {
// ...

+ interface SessionData extends HydrogenSessionData {}
}
```
6 changes: 6 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
@shopify:registry=https://registry.npmjs.com
progress=false

# Ensure Vite can optimize these deps in PNPM
public-hoist-pattern[]=textr
public-hoist-pattern[]=cookie
public-hoist-pattern[]=set-cookie-parser
public-hoist-pattern[]=content-security-policy-builder
66 changes: 3 additions & 63 deletions app/components/AddToCartButton.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import type {CartLineInput} from '@shopify/hydrogen/storefront-api-types';
import type {ShopifyAddToCartPayload} from '@shopify/hydrogen';
import {
AnalyticsEventName,
CartForm,
getClientBrowserParameters,
sendShopifyAnalytics,
} from '@shopify/hydrogen';
import {CartForm} from '@shopify/hydrogen';
import type {FetcherWithComponents} from '@remix-run/react';
import {useEffect} from 'react';

import {Button} from '~/components/Button';
import {usePageAnalytics} from '~/hooks/usePageAnalytics';

export function AddToCartButton({
children,
Expand All @@ -19,7 +11,6 @@ export function AddToCartButton({
variant = 'primary',
width = 'full',
disabled,
analytics,
...props
}: {
children: React.ReactNode;
Expand All @@ -28,7 +19,6 @@ export function AddToCartButton({
variant?: 'primary' | 'secondary' | 'inline';
width?: 'auto' | 'full';
disabled?: boolean;
analytics?: unknown;
[key: string]: any;
}) {
return (
Expand All @@ -41,12 +31,7 @@ export function AddToCartButton({
>
{(fetcher: FetcherWithComponents<any>) => {
return (
<AddToCartAnalytics fetcher={fetcher}>
<input
type="hidden"
name="analytics"
value={JSON.stringify(analytics)}
/>
<>
<Button
as="button"
type="submit"
Expand All @@ -58,54 +43,9 @@ export function AddToCartButton({
>
{children}
</Button>
</AddToCartAnalytics>
</>
);
}}
</CartForm>
);
}

function AddToCartAnalytics({
fetcher,
children,
}: {
fetcher: FetcherWithComponents<any>;
children: React.ReactNode;
}): JSX.Element {
const fetcherData = fetcher.data;
const formData = fetcher.formData;
const pageAnalytics = usePageAnalytics({hasUserConsent: true});

useEffect(() => {
if (formData) {
const cartData: Record<string, unknown> = {};
const cartInputs = CartForm.getFormInput(formData);

try {
if (cartInputs.inputs.analytics) {
const dataInForm: unknown = JSON.parse(
String(cartInputs.inputs.analytics),
);
Object.assign(cartData, dataInForm);
}
} catch {
// do nothing
}

if (Object.keys(cartData).length && fetcherData) {
const addToCartPayload: ShopifyAddToCartPayload = {
...getClientBrowserParameters(),
...pageAnalytics,
...cartData,
cartId: fetcherData.cart.id,
};

sendShopifyAnalytics({
eventName: AnalyticsEventName.ADD_TO_CART,
payload: addToCartPayload,
});
}
}
}, [fetcherData, formData, pageAnalytics]);
return <>{children}</>;
}
Loading

0 comments on commit d12043d

Please sign in to comment.