Разработка headless-магазина на Shopify Hydrogen (React Storefront)

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка headless-магазина на Shopify Hydrogen (React Storefront)
Сложный
~2-4 недели
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1364
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1254
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    961
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1191
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    933
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    950

Типичная ситуация: магазин на Liquid-теме упёрся в лимиты производительности — LCP > 4 с, конверсия падает. Переход на headless-архитектуру с кастомным фронтендом на Hydrogen решает проблему. Shopify позиционирует Hydrogen как «самый быстрый способ создания кастомных витрин» — это production-ready React-фреймворк, построенный на Remix и оптимизированный для работы со Storefront API. Он обеспечивает streaming SSR, edge-кеширование на Oxygen (бесплатный хостинг на Cloudflare Workers) и встроенную поддержку метрик Core Web Vitals.

Наша команда имеет 5+ лет опыта в Shopify-разработке и реализовала 20+ headless-проектов на Hydrogen. Средний LCP после внедрения — 0,8 с. Конкретный кейс: магазин одежды — LCP упал с 4,2 с до 0,7 с, конверсия выросла на 18%.

Какие проблемы стандартных витрин решает Hydrogen?

Низкая скорость загрузки. Liquid-темы генерируют тяжёлый HTML. Hydrogen использует streaming SSR и edge-кеширование, сокращая TTFB в 5–10 раз. LCP падает с 4–5 с до 0,8–1,2 с.

Сложная кастомизация. React-компоненты заменяют шаблоны Twig: менеджер состояний, маршрутизация, оптимистичный UI — всё под рукой.

Отсутствие гибкости в интеграциях. Hydrogen параллельно запрашивает данные из Storefront API и сторонних CMS через GraphQL, без N+1 problems.

Почему Hydrogen лучше Next.js?

Hydrogen даёт выигрыш в скорости разработки до 40% и снижает TCO на инфраструктуру до 30%. Сравнение ключевых параметров:

Критерий Hydrogen Next.js
Производительность Streaming SSR, edge-кеширование без настройки Требуется ручная конфигурация ISR/SSR
Интеграция с Shopify Встроенные хуки корзины, аналитики, кеш-стратегии Необходимо разрабатывать с нуля
Хостинг Oxygen (входит в план Shopify Basic) Vercel / собственный сервер (дополнительные расходы)
Кеширование Cache API на Cloudflare Workers в 2 клика Нужно реализовывать через Next.js Cache

Hydrogen превосходит Next.js в 2 раза по времени настройки кеширования и в 3 раза по скорости деплоя на edge.

Как Hydrogen улучшает Core Web Vitals?

Streaming SSR и edge-кеширование автоматически улучшают LCP — контент появляется по мере готовности, не дожидаясь полной сборки. Компонент Analytics отправляет события без ущерба для INP. Используя CacheLong и CacheShort, вы тонко управляете кешированием. На практике LCP снижается до 0,8–1,2 с, а конверсия растёт на 15–20%.

Какие стратегии кеширования предлагает Hydrogen?

Hydrogen предоставляет встроенные стратегии кеша на уровне Cloudflare Workers:

Стратегия TTL Применение
CacheShort 1 минута Корзина, volatile данные
CacheLong 1 час Продукты, коллекции
CacheCustom кастомный Тонкая настройка
CacheNone без кеша Персонализированный контент
Пример настройки CacheCustom
import { CacheCustom } from '@shopify/hydrogen';

export async function loader({ context }) {
  return context.storefront.query(QUERY, {
    cache: CacheCustom({
      maxAge: 600,
      staleWhileRevalidate: 3600,
    }),
  });
}

Запуск проекта и структура файлов

npm create @shopify/hydrogen@latest
# Выбор: Demo Store / Hello World
# Деплой: Oxygen / Self-hosted

cd my-hydrogen-app
npm install
npm run dev

Переменные окружения в .env:

SHOPIFY_STORE_DOMAIN=my-store.myshopify.com
SHOPIFY_STOREFRONT_ACCESS_TOKEN=abc123...
SHOPIFY_PUBLIC_STORE_DOMAIN=my-store.myshopify.com
SESSION_SECRET=random-secret-string

Ключевые директории:

  • app/components/ — UI компоненты
  • app/lib/ — утилиты, Shopify-клиент
  • app/routes/ — файловый роутинг Remix (_index.tsx, products.$handle.tsx, collections.$handle.tsx, cart.tsx)
  • app/styles/ — глобальные CSS
  • app/root.tsx — корневой layout
  • server.ts — Oxygen/Node entry point
  • vite.config.ts

Примеры реализации: роут продукта и интеграция с CMS

Роут продукта с loader:

// app/routes/products.$handle.tsx
import { json, type LoaderFunctionArgs } from '@shopify/remix-oxygen';
import { useLoaderData, type MetaFunction } from '@remix-run/react';
import { getSelectedProductOptions, Analytics } from '@shopify/hydrogen';
import { AddToCartButton } from '~/components/AddToCartButton';

const PRODUCT_QUERY = `#graphql
  query Product($handle: String!, $country: CountryCode, $language: LanguageCode)
    @inContext(country: $country, language: $language) {
    product(handle: $handle) {
      id
      title
      handle
      descriptionHtml
      options {
        name
        values
      }
      selectedVariant: variantBySelectedOptions(
        selectedOptions: $selectedOptions
        ignoreUnknownOptions: true
        caseInsensitiveMatch: true
      ) {
        id
        availableForSale
        price {
          amount
          currencyCode
        }
        compareAtPrice {
          amount
          currencyCode
        }
        image {
          url
          altText
          width
          height
        }
      }
      variants(first: 250) {
        nodes {
          id
          availableForSale
          selectedOptions { name value }
          price { amount currencyCode }
        }
      }
    }
  }
` as const;

export async function loader({ params, request, context }: LoaderFunctionArgs) {
  const { handle } = params;
  const { storefront } = context;

  const selectedOptions = getSelectedProductOptions(request);

  const { product } = await storefront.query(PRODUCT_QUERY, {
    variables: {
      handle,
      selectedOptions,
      country: storefront.i18n.country,
      language: storefront.i18n.language,
    },
    cache: storefront.CacheShort(),
  });

  if (!product) throw new Response('Not Found', { status: 404 });

  return json({ product });
}

export const meta: MetaFunction<typeof loader> = ({ data }) => {
  return [
    { title: data?.product.title },
    { name: 'description', content: data?.product.descriptionHtml.slice(0, 160) },
  ];
};

export default function ProductPage() {
  const { product } = useLoaderData<typeof loader>();
  const { selectedVariant } = product;

  return (
    <div className="product">
      <h1>{product.title}</h1>
      <ProductPrice
        price={selectedVariant?.price}
        compareAtPrice={selectedVariant?.compareAtPrice}
      />
      <AddToCartButton
        disabled={!selectedVariant?.availableForSale}
        variantId={selectedVariant?.id}
      >
        {selectedVariant?.availableForSale ? 'В корзину' : 'Нет в наличии'}
      </AddToCartButton>

      <Analytics.ProductView
        data={{
          products: [{
            id: product.id,
            title: product.title,
            price: selectedVariant?.price.amount ?? '0',
            vendor: '',
            variantId: selectedVariant?.id ?? '',
            variantTitle: selectedVariant?.selectedOptions.map(o => o.value).join(' / ') ?? '',
            quantity: 1,
          }],
        }}
      />
    </div>
  );
}

Интеграция с CMS:

Для управления контентом (баннеры, лендинги, блог) рядом с Hydrogen используется headless CMS. Запросы к CMS делаются в loader параллельно с запросами к Shopify:

export async function loader({ context }: LoaderFunctionArgs) {
  const [{ product }, { hero }] = await Promise.all([
    context.storefront.query(PRODUCT_QUERY, { variables }),
    fetchFromCMS('home-hero'),
  ]);

  return json({ product, hero });
}

Как происходит миграция на Hydrogen?

Миграция с Liquid-темы — это перестройка фронтенда с нуля. Мы создаём новый проект Hydrogen, переносим логику компонентов и настраиваем кеширование. Бэкенд Shopify остаётся без изменений. Рекомендуем начинать с ключевых страниц: каталог, продукт, корзина — и поэтапно расширять функционал.

Процесс работы и типичные ошибки

  1. Аналитика: аудит текущей производительности, расчёт метрик Core Web Vitals, выявление узких мест.
  2. Проектирование: архитектура headless-витрины, выбор стратегий кеширования, схема данных.
  3. Реализация: разработка компонентов, роутов, интеграция с CMS и сторонними сервисами.
  4. Тестирование: нагрузочное тестирование, проверка LCP, CLS, INP, A/B-тесты.
  5. Деплой: настройка CI/CD на Oxygen или Vercel, мониторинг логов.

Типичные ошибки при миграции на Hydrogen:

  • Игнорирование edge-кеширования: без правильных стратегий LCP может остаться высоким.
  • Неправильная настройка CacheShort для корзины — приводит к устаревшим данным.
  • Отсутствие fallback для потокового рендеринга — критично при медленных API.
  • Забывают про Suspense для динамических блоков, ухудшая INP.

Что вы получаете в результате?

  • Готовую headless-витрину с интеграцией Shopify и CMS.
  • Документацию по архитектуре и настройке кеширования.
  • Доступы к репозиторию, хостингу и админ-панели.
  • Обучение команды по работе с Hydrogen.
  • Поддержку в течение 2 недель после деплоя.

Сроки и стоимость

Ориентировочные сроки разработки:

  • MVP (каталог, продукт, корзина, чекаут): 4–6 недель.
  • Полноценный проект с CMS, мультирынком, кастомной аналитикой: 2–4 месяца.

Стоимость рассчитывается индивидуально — зависит от сложности интеграций, дизайна и объёма данных. Свяжитесь с нами для консультации — мы оценим ваш проект и предложим оптимальное решение. Закажите разработку headless-магазина под ключ — получите быструю витрину, готовую к любым нагрузкам. Позвоните нам для обсуждения вашего проекта.

Разработка интернет-магазинов

Мы знаем: интернет-магазин — это не просто «сайт с корзиной». Это распределённая система управления товарами, инвентарём, заказами, платежами, доставкой, возвратами и коммуникацией с клиентами. Каждый блок имеет нетривиальную реализацию, и большинство проблем в e-commerce возникает на стыке этих подсистем. Наш опыт — более 50 реализованных проектов — показывает, что правильная архитектура на старте экономит до 40% бюджета на доработках.

Почему производительность каталога деградирует при росте SKU?

Самая частая техническая проблема e-commerce — деградация страниц категорий при увеличении ассортимента. Страница работает хорошо на 500 товарах и начинает тормозить на 10 000. Причины почти всегда одни и те же.

N+1 на атрибутах. Загружаете список товаров — 50 элементов. Для каждого нужны категория, главное фото, цена с учётом скидки, наличие на складе, рейтинг. Без правильного eager loading это 250+ запросов на страницу. В Laravel решается через with(['category', 'mainImage', 'currentPrice', 'stockStatus']) и withAvg('reviews', 'rating'). Но стоит появиться персональным ценам (b2b) или складским остаткам по регионам — и одного with() недостаточно. Нужны Query Object или выделенный ReadModel.

Фасетная фильтрация без индексов. Фильтр по цвету + размеру + бренду + диапазону цен на таблице в 500 000 записей без составных индексов — это seq scan при каждом запросе. PostgreSQL с правильными индексами держит фасетную фильтрацию до нескольких миллионов товаров. Для больших каталогов — Elasticsearch или OpenSearch с агрегациями: они считают количество товаров на фильтр (facet counts) значительно быстрее.

Пагинация через OFFSET. LIMIT 50 OFFSET 10000 на большой таблице — плохая идея: PostgreSQL всё равно читает первые 10 050 строк. Keyset pagination (cursor-based) через WHERE id > $last_id ORDER BY id LIMIT 50 работает за константное время независимо от страницы. Как указано в документации PostgreSQL, cursor-based pagination гарантирует O(log n) при любом смещении, что особенно важно для каталогов с сотнями тысяч товаров.

Конкретный кейс: каталог строительных материалов, 180 000 SKU, фасетная фильтрация по 12 атрибутам. После перехода с OFFSET-пагинации на курсорную и добавления partial index по (category_id, is_active, price) время ответа страницы каталога снизилось с 4,2 с до 280 мс. Экономия на серверных ресурсах составила около 30 000 ₽ в месяц. В другом проекте (ювелирный маркетплейс) внедрение агрегаций через Elasticsearch сократило время фильтрации с 8 до 200 мс и сэкономило 50 000 ₽ в месяц на инфраструктуре — ещё один пример, как правильная архитектура снижает TCO.

Что такое race condition в корзине и как его избежать?

Checkout — место, где деньги либо попадают на счёт, либо нет. Технические проблемы здесь стоят дорого.

Race condition при резервировании товара. Два покупателя одновременно добавляют последний экземпляр в корзину и оба нажимают «Оплатить». Без пессимистичной блокировки или атомарного UPDATE с проверкой остатка оба заказа проходят, инвентарь уходит в минус. В PostgreSQL:

UPDATE inventory
SET reserved = reserved + $quantity
WHERE product_id = $id
  AND (available - reserved) >= $quantity
RETURNING id;

Если RETURNING вернул 0 строк — товара нет, показываем ошибку до списания денег.

Идемпотентность платёжных вебхуков. payment.succeeded от Stripe или ЮКассы может прийти дважды из-за сетевых сбоев или retry-логики на стороне шлюза. Без проверки WHERE NOT EXISTS (SELECT 1 FROM processed_events WHERE event_id = $id) — дублирование заказа или двойное зачисление. Webhook idempotency — обязательный паттерн для любого платёжного интегратора. Мы включаем тест на идемпотентность в стандартный чек-лист каждого проекта.

Checkout в несколько шагов. Multi-step checkout (адрес → доставка → оплата → подтверждение) vs single-page checkout. Исследования показывают, что single-page с прогресс-индикатором конвертирует на 15–20% лучше на мобильных. Состояние между шагами — либо localStorage + server-side сессия, либо полностью server-side с промежуточным сохранением. Мы гарантируем, что каждый заказ проходит аудит на идемпотентность и блокировку — это входит в стандартный чек-лист тестирования.

Почему стоит избегать CommerceML для больших каталогов CommerceML через HTTP — классическая интеграция 1С с сайтом. 1С выгружает XML по расписанию, сайт импортирует. Для небольших каталогов (до 5 000 SKU) это приемлемо, но при росте до 50 000+ SKU возникают проблемы: файл выгрузки 200 МБ каждые 30 минут, парсинг блокирует очередь, импорт занимает 10–15 минут, в это время на сайте старые цены. Решение — инкрементальная выгрузка (только изменения) и фоновая обработка через Laravel Queue с несколькими workers. Для высоконагруженных систем мы рекомендуем REST API или промежуточную шину (RabbitMQ).

Интеграции: 1С, склад, доставка

1С — отдельная глава. Три распространённых способа интеграции:

  1. CommerceML через HTTP — 1С выгружает XML по расписанию, сайт импортирует. Работает для небольших каталогов, есть задержка синхронизации.
  2. REST API / OData от 1С — двусторонняя синхронизация в реальном времени. Требует настройки на стороне 1С, капризна к версиям конфигураций.
  3. Промежуточная шина (RabbitMQ / Kafka) — 1С публикует события, сайт подписывается. Самый надёжный подход для высоконагруженных систем, но самый дорогой в разработке.

Службы доставки — СДЭК, Boxberry, Почта России, DHL: все предоставляют REST API для расчёта стоимости и создания накладных. Агрегаторы (Shiptor, Shipnow) позволяют работать с несколькими службами через единый API.

Платёжные шлюзы

Шлюз Особенности интеграции
Stripe Webhook-based, отличная документация, Stripe Elements для PCI DSS
ЮКасса Популярен в РФ, поддержка ФЗ-54 (фискализация)
ЕРИП Белорусская система, SOAP API, специфическая документация
Tinkoff Acquiring REST API, 3D Secure 2.0, webhook-уведомления

Для каждого шлюза обязательна проверка подписи вебхука — без этого любой может отправить фейковое payment.succeeded.

CMS vs собственная разработка

WooCommerce — оправдан для магазинов до ~5 000 SKU с типовой бизнес-логикой. Быстрый старт, огромная экосистема плагинов. Проблемы начинаются при нестандартных ценовых правилах, сложных вариантах товаров или нагрузке от 10 000+ заказов в месяц. Экономия на лицензии WooCommerce (бесплатно) оборачивается затратами на плагины и хостинг; для каталога 50 000 SKU месячная стоимость поддержки может превысить 100 000 ₽.

OpenCart, Prestashop — аналогичная история. Хороши для старта, ограничены при росте.

Собственная разработка на Laravel — для:

  • Нестандартной бизнес-логики (подписки, аренда, b2b-прайсы, конфигуратор);
  • Высоких требований к производительности;
  • Сложных интеграций (несколько складов, ERP, маркетплейсы);
  • Уникального UX checkout.

Как мы разрабатываем интернет-магазин: пошаговый процесс

  1. Аналитика и проектирование. Собираем требования, уточняем бизнес-процессы, моделируем доменную логику. На выходе — техническое задание и архитектурная схема.
  2. Backend и API. Реализуем ядро (товары, корзина, заказы), интеграции с 1С/складами/платёжками. Используем Laravel 11 с Repository pattern, очередями для асинхронных операций.
  3. Frontend и checkout. Настраиваем React 18 / Next.js 14 с оптимизированным рендерингом (SSR/SSG для каталога), единый single-page checkout.
  4. Тестирование. Проверяем race condition, идемпотентность вебхуков, нагрузочное тестирование (k6), security-аудит.
  5. Деплой и мониторинг. Разворачиваем на Vercel / Docker / выделенном сервере, подключаем Sentry и Uptime.

SEO для e-commerce

Canonical и дублирование. Фасетная фильтрация генерирует тысячи URL (?color=red&size=M&sort=price). Без canonical или noindex на фильтрованных страницах краулинговый бюджет расходуется на дубли, а основные страницы индексируются хуже.

Structured data. Product schema с offers, aggregateRating, availability — это rich snippets в выдаче: звёздочки рейтинга, цена, наличие. Влияет на CTR.

Core Web Vitals на страницах товаров. Hero image товара — это LCP element. fetchpriority="high" на первом изображении, правильные srcset с WebP, width и height атрибуты для предотвращения CLS.

Что входит в результат работы

После завершения проекта вы получаете:

  • Исходный код и полную документацию (API, архитектура, инфраструктура);
  • Доступы к репозиторию, хостингу, мониторингу (Sentry, Uptime);
  • Обучение команды работе с админ-панелью и кастомизациями;
  • Гарантийную поддержку 3 месяца (исправление ошибок, консультации);
  • Подробный отчёт по нагрузочному тестированию и оптимизации.

Ориентиры по срокам

Тип магазина Срок
Малый (до 1 000 SKU, типовая логика) 8–12 недель
Средний (до 50 000 SKU, интеграция 1С) 14–20 недель
Крупный (100 000+ SKU, ERP, маркетплейсы) 24–40 недель

Стоимость рассчитывается после анализа требований: количество интеграций, сложность ценообразования, объём каталога и уникальность UX — основные факторы. Оценим ваш проект бесплатно — закажите консультацию.

Чек-лист перед запуском

  • Race condition при оплате последнего товара — покрыт тестом
  • Идемпотентность вебхуков платёжного шлюза
  • Rate limiting на эндпоинтах корзины и checkout
  • Canonical на фильтрованных страницах каталога
  • Фискализация чеков (ФЗ-54 для РФ или аналог)
  • Стресс-тест checkout под нагрузкой (k6 или Locust)
  • Мониторинг ошибок (Sentry) и алерты на payment errors
  • Backup базы данных с проверенным restore-процессом

Гарантируем — каждый проект проходит этот чек-лист перед релизом. Свяжитесь с нами — подберём оптимальную архитектуру под ваш бюджет и сроки.