Hidrojen: Shopify'ın Ticaret Çerçevesi

Shopify Hidrojen vitrinler oluşturmaya yönelik resmi React çerçevesidir başsız Shopify. Mevcut versiyonda (Hidrojen 2.x) üzerine inşa edilmiştir. Remiksler, Bir mimari için yerel Web API'lerinden ve Sunucu Eylemlerinden yararlanan React meta çerçevesi giderek iyileşti.

Oksijen Shopify'ın Hidrojen projelerine yönelik küresel barındırma çalışma zamanıdır: dayalı Cloudflare Çalışanları (V8 İzolatlar), sunucu tarafı kodunu çalıştırır uçta — son kullanıcıya en yakın veri merkezlerinde. Sonuç bir Küresel olarak 30-80 ms'lik TTFB (İlk Bayta Kadar Süre), bir sunucuyla elde edilmesi imkansızdır geleneksel merkezileştirilmiş.

Hidrojen Projesi Kurulumu

# 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

Hydrogen projesinin yapısı Remix'e dayalıdır ve klasik olana çok benzemektedir. dosya tabanlı yönlendirme:

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

Vitrin API'si: Hidrojen Çekirdeği

Hydrogen, Shopify'a şu adresten bağlanır: Vitrin API'si GraphQL. Her operasyon ticaret bir GraphQL sorgusu veya mutasyonudur. Hidrojen önceden yapılandırılmış istemciyi sağlar:

// 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>
  );
}

Sepet API'si: Sepetinizi Hidrojenle Yönetin

Hidrojen arabayı şu şekilde yönetir: Shopify'ın Sepet API'si (dayanarak GraphQL Mutasyonları). Çerçeve, anında güncellemeler için iyimser bir kullanıcı arayüzü sistemi içerir:

// 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>
  );
}

Oksijeni Önbelleğe Alma: Performansın Anahtarı

Oxygen, Cloudflare Workers sınırında Hidrojen kodunu çalıştırır. Önbellek şu şekilde yönetilir: Cloudflare yerel API'leri ve Hidrojen yardımcıları:

// 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
});

Sıvıdan Hidrojene Geçiş teması

Mevcut bir Shopify temanız varsa Hydrogen'e geçmek önemli bir projedir. Önerilen yaklaşım artımlıdır:

  1. Öncelikli sayfaları belirleyin: ürün sayfaları ve koleksiyon sayfaları daha fazla trafik alıyorlar. Oradan başla.
  2. Hydrogen'i alt alan adınız olarak kullanın: shop.tuodominio.com Hidrojen üzerinde, tuodominio.com Sıvı temasında. Performansı test edin ve ölçün.
  3. Ödeme işlemini ayrı olarak taşı: Shopify ödeme işlemini kendi hesabıyla gerçekleştirir yerel sistem (Ödeme Genişletilebilirliği) — onu sıfırdan yeniden yazmanıza gerek yoktur.
  4. Kademeli olarak aktar: sayfa sayfa, rota rota.

Hidrojenin Bilinmesi Gereken Sınırlamaları

  • Shopify tarafından yönetilen ödeme: ödeme her zaman etki alanında yapılır Shopify (checkout.shopify.com). Görünümü Checkout ile özelleştirebilirsiniz Genişletilebilirlik, ancak ödemeyi kendi ödemenizle değiştiremezsiniz.
  • Kısmi satıcı bağımlılığı: Hidrojen/Oksijen yalnızca Shopify ile çalışır arka uç. Ticaret platformunu değiştirmek istiyorsanız ön ucu yeniden yazmanız gerekir.
  • API hız sınırları: Storefront API'nin hız sınırlaması vardır. Yoğun trafik için yüksekse, agresif önbelleğe almayı veya sunucu tarafı önbelleğe almayla BFF modelini düşünün.

Sonuçlar ve Sonraki Adımlar

Hidrojen + Oksijen, halihazırda ekosistemde çalışanlar için en pragmatik seçimdir Shopify ve kafasız gitmek istiyor. Remix, GraphQL, edge bilişim ve Yerel ödeme yönetimi, yüksek performanslı vitrinler için mükemmel bir temel sunar.

Bir sonraki makalede inceleyeceğiz Medusa.js, en iyi açık kaynak alternatifi başsız: tamamen kendi kendini barındırabilen, modüler mimari ve satıcıya bağımlı olmama.