Shopify Hidrogen și oxigen: construirea unei vitrine cu reacție performantă la margine
Hydrogen este cadrul oficial Shopify React bazat pe Remix: Storefront API GraphQL, componente primitive cărucioare, SSR streaming pe Oxygen (edge Cloudflare Workers), optimizare cu strategii de stocare în cache și cum să migrați de la o temă tradițională Liquid.
Hidrogen: Cadrul de comerț Shopify
Shopify Hydrogen este cadrul oficial React pentru construirea de vitrine Shopify fără cap. În versiunea actuală (Hydrogen 2.x) este construit pe acesta Remixuri, meta-cadru React care folosește API-urile web native și acțiunile serverului pentru o arhitectură imbunatatit progresiv.
Oxigen este timpul de găzduire global al Shopify pentru proiectele Hydrogen: bazat pe Lucrătorii Cloudflare (V8 izolate), rulează cod pe server la margine — în centrele de date cele mai apropiate de utilizatorul final. Rezultatul este unul TTFB (Time to First Byte) de 30-80ms la nivel global, imposibil de realizat cu un server tradițional centralizat.
Crearea unui proiect de hidrogen
# Crea un nuovo progetto Hydrogen
npm create @shopify/hydrogen@latest my-store
# Rispondi alle domande:
# - Store domain: mystore.myshopify.com
# - Storefront API token: [da Shopify Admin > Apps > Develop apps]
# - Language: TypeScript
# - CSS: Tailwind CSS
cd my-store
npm run dev
# Apre su http://localhost:3000
Structura unui proiect Hydrogen se bazează pe Remix și foarte asemănătoare cu cea clasică rutare bazată pe fișiere:
app/
├── components/ # Componenti UI riutilizzabili
│ ├── Cart.tsx # Componente carrello
│ ├── ProductCard.tsx # Card prodotto
│ └── Header.tsx # Header con mini-cart
├── routes/ # File-based routing Remix
│ ├── _index.tsx # Homepage (/)
│ ├── products.$handle.tsx # Pagina prodotto (/products/[handle])
│ ├── collections.$handle.tsx # Collection (/collections/[handle])
│ └── cart.tsx # Pagina carrello (/cart)
├── lib/
│ ├── fragments.ts # GraphQL fragments riutilizzabili
│ └── utils.ts # Utility functions
├── root.tsx # Root layout
└── entry.server.tsx # Server-side entry point
Storefront API: Miezul de hidrogen
Hydrogen se conectează la Shopify prin intermediul Storefront API GraphQL. Fiecare operație comerțul este o interogare sau o mutație GraphQL. Hydrogen oferă clientului preconfigurat:
// app/routes/products.$handle.tsx
// Pagina dettaglio prodotto
import {json} from '@shopify/remix-oxygen';
import {useLoaderData} from '@remix-run/react';
import {Image, Money} from '@shopify/hydrogen';
import type {LoaderFunctionArgs} from '@shopify/remix-oxygen';
const PRODUCT_QUERY = `#graphql
query Product($handle: String!, $selectedOptions: [SelectedOptionInput!]!) {
product(handle: $handle) {
id
title
descriptionHtml
vendor
selectedVariant: variantBySelectedOptions(selectedOptions: $selectedOptions) {
id
availableForSale
selectedOptions { name value }
price { amount currencyCode }
compareAtPrice { amount currencyCode }
image { url altText width height }
}
options {
name
values
}
variants(first: 100) {
nodes {
id
availableForSale
selectedOptions { name value }
price { amount currencyCode }
}
}
}
}
`;
export async function loader({ params, context, request }: LoaderFunctionArgs) {
const { handle } = params;
const { storefront } = context;
// Leggi le opzioni selezionate dalla URL (?color=red&size=M)
const searchParams = new URL(request.url).searchParams;
const selectedOptions = [];
for (const [name, value] of searchParams) {
selectedOptions.push({ name, value });
}
const { product } = await storefront.query(PRODUCT_QUERY, {
variables: { handle, selectedOptions },
cache: storefront.CacheShort(), // cache di 1 minuto su Oxygen
});
if (!product) throw new Response('Not Found', { status: 404 });
return json({ product });
}
export default function Product() {
const { product } = useLoaderData<typeof loader>();
const { selectedVariant } = product;
return (
<div className="product">
{selectedVariant?.image && (
<Image
data={selectedVariant.image}
className="product-image"
sizes="(min-width: 768px) 50vw, 100vw"
/>
)}
<h1>{product.title}</h1>
{selectedVariant && (
<Money data={selectedVariant.price} />
)}
<AddToCartButton variant={selectedVariant} />
</div>
);
}
Cart API: gestionați-vă coșul cu hidrogen
Hidrogenul gestionează căruciorul prin intermediul API-ul Coș de la Shopify (bazat pe Mutații GraphQL). Cadrul include un sistem UI optimist pentru actualizări imediate:
// Aggiungere un prodotto al carrello
const ADD_TO_CART_MUTATION = `#graphql
mutation cartLinesAdd($cartId: ID!, $lines: [CartLineInput!]!) {
cartLinesAdd(cartId: $cartId, lines: $lines) {
cart {
id
totalQuantity
cost {
totalAmount { amount currencyCode }
}
lines(first: 100) {
nodes {
id
quantity
merchandise {
... on ProductVariant {
id
title
product { title }
price { amount currencyCode }
image { url altText }
}
}
}
}
}
}
}
`;
// Componente AddToCartButton con Fetcher di Remix
import { useFetcher } from '@remix-run/react';
function AddToCartButton({ variant }: { variant: ProductVariant }) {
const fetcher = useFetcher();
const isAdding = fetcher.state !== 'idle';
return (
<fetcher.Form method="POST" action="/cart">
<input type="hidden" name="intent" value="add" />
<input type="hidden" name="variantId" value={variant.id} />
<button
type="submit"
disabled={!variant.availableForSale || isAdding}
className="add-to-cart-btn"
>
{isAdding ? 'Aggiunta...' : 'Aggiungi al Carrello'}
</button>
</fetcher.Form>
);
}
Memorarea în cache pe oxigen: cheia performanței
Oxygen rulează codul Hydrogen pe marginea Cloudflare Workers. Cache-ul este gestionat prin API-uri native Cloudflare și ajutoare Hydrogen:
// Strategie di cache disponibili in Hydrogen
// Definiamo cache personalizzate per tipo di contenuto
// Cache lunga per pagine prodotto (aggiornamento raro)
export async function loader({ context }: LoaderFunctionArgs) {
const { storefront } = context;
const data = await storefront.query(PRODUCTS_QUERY, {
cache: storefront.CacheLong(), // cache di 1 ora
});
return json(data, {
headers: {
'Cache-Control': 'public, max-age=3600, stale-while-revalidate=86400',
},
});
}
// Cache breve per dati variabili (inventory, prezzi)
const inventoryData = await storefront.query(INVENTORY_QUERY, {
cache: storefront.CacheShort(), // cache di 60 secondi
});
// Nessuna cache per dati personalizzati (cart, customer)
const customerData = await storefront.query(CUSTOMER_QUERY, {
cache: storefront.NoStore(), // no-cache
});
Migrarea de la tema Lichid la Hidrogen
Dacă aveți o temă Shopify existentă, migrarea la Hydrogen este un proiect semnificativ. Abordarea recomandată este progresivă:
- Identificați paginile prioritare: pagini de produse și pagini de colecție primesc mai mult trafic. Începeți de acolo.
-
Utilizați hidrogen ca subdomeniu:
shop.tuodominio.compe hidrogen,tuodominio.compe tema Lichid. Testați și măsurați performanța. - Migrați plata separat: Shopify se ocupă de plată cu propriile sale sistem nativ (Extensibilitate de checkout) — nu trebuie să-l rescrieți de la zero.
- Transferați treptat: pagină cu pagină, traseu după traseu.
Limitările hidrogenului de cunoscut
-
Checkout gestionat de Shopify: checkout este întotdeauna pe domeniu
Shopify (
checkout.shopify.com). Puteți personaliza aspectul cu Checkout Extensibilitate, dar nu puteți înlocui plata cu propria dvs. - Blocare parțială a furnizorului: Hydrogen/Oxygen funcționează numai cu Shopify ca backend. Dacă doriți să schimbați platforma de comerț, trebuie să rescrieți interfața.
- Limitele ratei API: API-ul Storefront are limitare de rată. Pentru trafic intens mare luați în considerare cache agresivă sau un model BFF cu cache pe server.
Concluzii și pașii următori
Hidrogen + Oxigen este cea mai pragmatică alegere pentru cei care lucrează deja în ecosistem Shopify și vrea să rămână fără cap. Combinația de Remix, GraphQL, edge computing și Managementul nativ al caselor oferă o bază excelentă pentru vitrinele de înaltă performanță.
În următorul articol vom explora Medusa.js, cea mai bună alternativă open-source fără cap: arhitectură modulară complet auto-găzduită și fără blocare a furnizorului.







