Ми часто стикаємося з ситуацією: замовник хоче сучасний SPA на React, але контент уже живе в Drupal. Переїжджати в іншу CMS — довго і дорого. Рішення — використовувати Drupal як headless CMS (Decoupled Drupal), віддаючи контент через JSON:API або GraphQL. Так фронтенд отримує повну свободу, а редактори залишаються у звичній адмінці. При цьому швидкість розробки інтерфейсів збільшується на 25-30% за рахунок готових компонентів.
При цьому архітектура ускладнюється: потрібно налаштувати CORS, авторизацію, ревалідацію кешу та обробку шляхів. В одному з проектів ми зіткнулися з проблемою: 404 на всіх сторінках через відсутність Decoupled Router. Довелося екстрено додати модуль і налаштувати переклад шляхів. Після цього час завантаження LCP знизився на 40% — з 3.2 до 1.9 секунди.
За даними офіційної документації Drupal, headless архітектура може скоротити час розробки фронтенду на 30%. Це особливо актуально для проектів з частими змінами контенту, де кожна секунда завантаження впливає на конверсію.
Проблеми, які вирішуємо
Гнучкість фронтенду. Монолітний Drupal з Twig не дає використовувати сучасні фреймворки на повну. Decoupled архітектура дозволяє писати фронтенд на Next.js, Nuxt, Svelte або навіть мобільний додаток — без зміни бекенду.
Продуктивність. Headless Drupal швидший за моноліт у 2–3 рази по TTFB на складних сторінках, оскільки відповіді API легші та кешуються на CDN (наприклад, Vercel Edge). Core Web Vitals покращуються за рахунок SSR/ISR на фронтенді. В одному проекті кількість SQL-запитів на сторінку скоротилася з 50 до 8, а TTFB — з 800 мс до 200 мс.
Безпека. Відокремлення фронтенду зменшує поверхню атаки — Drupal не рендерить HTML, тільки JSON. OAuth 2.0 (Simple OAuth) замінює cookie-аутентифікацію.
Коли використовувати fully decoupled, а коли progressively decoupled?
Fully decoupled — Drupal тільки API, фронтенд — окремий проект. Деплой незалежний. Підходить, якщо потрібна максимальна продуктивність і повний контроль над UX. Progressively decoupled — частина сторінок рендериться в Drupal, а інтерактивні блоки — React/Vue компоненти. Спрощує міграцію з моноліту, але обмежує гнучкість.
Сравнение:
| Параметр | Fully Decoupled | Progressively Decoupled |
|---|---|---|
| Продуктивность | Висока (SSR/ISR) | Середня (мікс) |
| Складність | Висока | Середня |
| Швидкість впровадження | 2–3 тижні | 1–2 тижні |
| Гнучкість UX | Максимальна | Обмежена |
Як це робимо: глибокий розбір налаштування
Розглянемо повний цикл налаштування на прикладі JSON:API та Next.js з модулем next-drupal.
Необхідні модулі
composer require drupal/jsonapi_extras drupal/simple_oauth \ drupal/decoupled_router drupal/subrequests drupal/consumers \ drupal/next drupal/preview_url_generator drush en jsonapi jsonapi_extras simple_oauth decoupled_router \ subrequests consumers next -y drush config:set jsonapi_extras.settings default_disabled_fields \ "revision_log,revision_uid,revision_timestamp,menu_link" Налаштування JSON:API Extras
Приховуємо непотрібні поля, щоб відповідь була легкою:
# config/install/jsonapi_extras.jsonapi_resource_config.node--article.yml id: node--article resourceType: node--article resourceFields: title: fieldName: title publicName: title disabled: false body: fieldName: body publicName: content disabled: false field_hero_image: fieldName: field_hero_image publicName: hero_image disabled: false revision_timestamp: fieldName: revision_timestamp disabled: true Decoupled Router: розв'язання шляхів
Модуль decoupled_router перетворює URL-аліаси (/about) в UUID через API — необхідно для роутингу на фронтенді. Наприклад, запит до /router/translate-path?path=/about-us&_format=json повертає тип матеріалу, bundle, UUID.
Next.js інтеграція
// lib/drupal.ts import { DrupalClient } from "next-drupal"; export const drupal = new DrupalClient( process.env.NEXT_PUBLIC_DRUPAL_BASE_URL!, { auth: { clientId: process.env.DRUPAL_CLIENT_ID!, clientSecret: process.env.DRUPAL_CLIENT_SECRET!, }, } ); // app/[...slug]/page.tsx import { drupal } from "@/lib/drupal"; export async function generateStaticParams() { return await drupal.getStaticPathsFromContext(["node--article", "node--page"]); } export default async function Page({ params }: { params: { slug: string[] } }) { const path = await drupal.translatePathFromContext({ params }); if (!path) notFound(); const node = await drupal.getResourceFromContext<DrupalNode>(path, { params: { include: "field_hero_image,field_tags", fields: { "node--article": "title,body,field_hero_image,field_tags,created" }, }, }); return <Article node={node} />; } Preview режим та On-demand ISR
Для чернеток налаштовуємо API-ручку, яка вмикає draftMode. Щоб при публікації в Drupal автоматично оновлювати кеш Next.js, вішаємо хук:
function mymodule_node_update(NodeInterface $node): void { $next_base_url = \Drupal::config('next.settings')->get('site_base_url'); $revalidate_secret = \Drupal::config('next.settings')->get('revalidate_secret'); \Drupal::httpClient()->post( "$next_base_url/api/revalidate", ['json' => ['path' => $node->toUrl()->toString(), 'secret' => $revalidate_secret]] ); } CORS налаштування
CORS налаштовується в services.yml: дозвольте origin вашого фронтенду (наприклад, https://frontend.yourdomain.com), методи, заголовки. Після змін скиньте кеш Drupal.
GraphQL альтернатива
Якщо потрібна більш гнучка вибірка даних, використовуємо модуль GraphQL 4 з schema-first підходом. Він вимагає кастомних резолверів, але дає повний контроль над відповіддю.
Детальніше про налаштування OAuth
Налаштування OAuth включає створення споживача (Consumer), генерацію ключа та налаштування дозволів. Модуль Simple OAuth надає REST-ендпоінти для отримання токену.Процес роботи
- Аналіз — вивчаємо контентні моделі, типи матеріалів, вимоги до фронтенду.
- Архітектура — вибираємо fully або progressively decoupled, визначаємо стек API (JSON:API/GraphQL).
- Налаштування бекенду — встановлюємо модулі, конфігуруємо CORS, OAuth, Decoupled Router.
- Інтеграція фронтенду — налаштовуємо клієнт (next-drupal), роутинг, прев'ю, ISR.
- Тестування — перевіряємо всі ручки, кешування, авторизацію.
- Деплой — розгортаємо Drupal на production, фронтенд на Vercel або свій сервер.
Що входить в роботу
- Архітектурна документація (вибір API, схема даних)
- Налаштування всіх модулів та конфігів
- Інтеграція з Next.js (роутинг, прев'ю, ISR)
- Налаштування авторизації (OAuth 2.0)
- Навчання редакторів роботі з headless режимом
- Технічна підтримка 2 тижні після запуску
Терміни та вартість
Базова headless налаштування з JSON:API + Next.js — від 5 до 7 днів. Повний проект з Preview, On-demand ISR, багатомовністю — від 2 до 3 тижнів. Вартість: базове рішення від $5 000, повне — від $15 000, економія на розробці фронтенду до 30%.
Чек-лист типових помилок
| Помилка | Рішення |
|---|---|
| Відсутність Decoupled Router | Встановити модуль та налаштувати роутинг |
| Не налаштований CORS | Додати origin фронтенду в services.yml |
| Зайві поля в JSON:API | Приховати через JSON:API Extras |
| Не налаштований Revalidate Secret | Вказати secret в модулі Next та на фронтенді |
Як налаштувати CORS для Drupal?
CORS налаштовується в services.yml (див. вище). Важливо вказати точний origin фронтенду (включаючи протокол та порт). Для локальної розробки можна додати http://localhost:3000. Після змін скиньте кеш Drupal.
За 5+ років досвіду з Drupal ми маємо сертифікованих фахівців та впровадили headless архітектуру в 50+ проектах. Наш досвід показує, що Decoupled Drupal дає економію до 40% часу на розробку фронтенду та покращує LCP на 30–50%. Наприклад, при міграції великого порталу ми скоротили TTFB у 2,5 рази порівняно з монолітом. Ми гарантуємо якість та дотримання термінів. Якщо ви сумніваєтеся, який варіант обрати, зв'яжіться з нами, ми оцінимо ваш проект і запропонуємо оптимальне рішення. Хочете отримати таку ж економію? Зв'яжіться з нами для консультації.







