Коли headless WordPress виправданий?
У вас уже є сайт на WordPress, але клієнти скаржаться на повільне завантаження, а редактори звикли до адмінки. Переїжджати на іншу CMS — ризик втратити контент і SEO-позиції. Headless WordPress залишає адмінку для контенту, а фронтенд переписується на сучасному стеку (Next.js, React, Vue). Це дає швидкість SPA, гнучкість компонентів і звичний редактор. Не варто обирати headless, якщо сайт будується з нуля і немає жорстких вимог — звичайний WordPress простіший і дешевший.
Як ми це робимо: розбір на реальному кейсі
Для одного з проєктів ми використовували WordPress + Next.js 14 з ISR. Вихідні дані: 10 000 постів, 5 категорій, ACF-поля для портфоліо. Проблема — сторінки завантажувалися за 4 секунди (LCP > 4s). Після headless-інтеграції LCP впав до 1.2 с, TTFB — з 800 до 120 мс. Зниження навантаження на сервер у 3 рази (з 8 до 3 запитів на сторінку).
Ключові кроки:
- Налаштування REST API — увімкнули
_fieldsдля мінімізації відповіді, вимкнули невикористовувані ендпоінти. - CORS та безпека — дозволили лише домен фронту, додали валідацію Origin.
- ACF в API — через
register_rest_fieldдодали метаполя прямо у відповідь. - Next.js API-клієнт — єдиний fetch з ISR revalidate.
- Webhook on-demand revalidation — при публікації посту WordPress відправляє POST на
/api/revalidateв Next.js.
Результат: швидкість завантаження зросла на 70%, SEO-трафік збільшився на 25% за місяць.
Технічна реалізація: від REST API до on-demand revalidation
WP REST API: базові ендпоінти та оптимізація
WordPress REST API включено з версії 4.7. Базовий URL: https://site.com/wp-json/wp/v2/. Критично важливо використовувати параметр _fields — за замовчуванням відповідь містить десятки полів, більшість не потрібні.
# Список постів з потрібними полями GET /wp-json/wp/v2/posts?_fields=id,title,slug,date,excerpt,featured_media&per_page=10 Як налаштувати CORS для headless WordPress?
add_action('rest_api_init', function () { remove_filter('rest_pre_serve_request', 'rest_send_cors_headers'); add_filter('rest_pre_serve_request', function ($value) { $allowed_origins = ['https://frontend.site.com', 'http://localhost:3000']; $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; if (in_array($origin, $allowed_origins, true)) { header("Access-Control-Allow-Origin: {$origin}"); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Headers: Authorization, Content-Type'); } return $value; }); }, 15); Розширення REST API: ACF та кастомні ендпоінти
add_action('rest_api_init', function () { register_rest_field('portfolio', 'acf', [ 'get_callback' => function ($post) { return get_fields($post['id']); }, 'schema' => ['type' => 'object'], ]); register_rest_route('app/v1', '/home', [ 'methods' => 'GET', 'callback' => function (WP_REST_Request $request) { return rest_ensure_response([ 'hero' => get_fields(get_option('home_hero_page_id')), 'featured' => array_map(fn($p) => [ 'id' => $p->ID, 'title' => get_the_title($p), 'slug' => $p->post_name ], get_posts(['post_type' => 'portfolio', 'posts_per_page' => 3])), ]); }, 'permission_callback' => '__return_true', ]); }); Інтеграція з Next.js: ISR та preview mode
const WP_API = process.env.WP_API_URL; export async function getPosts(params = {}) { const url = new URL(`${WP_API}/posts`); url.searchParams.set('_fields', 'id,slug,title,excerpt,date,featured_image_url,acf'); const res = await fetch(url, { next: { revalidate: 60 } }); if (!res.ok) throw new Error(`WP API error: ${res.status}`); return { posts: await res.json(), total: Number(res.headers.get('X-WP-Total')) }; } Для preview mode додаємо API-роут /api/preview, який активує draftMode та редиректить на потрібний пост.
On-demand revalidation: WordPress → Next.js
При збереженні посту WordPress відправляє POST на /api/revalidate:
export async function POST(req: Request) { const { secret, slug } = await req.json(); if (secret !== process.env.REVALIDATE_SECRET) return Response.json({ error: 'Forbidden' }, { status: 403 }); revalidatePath(`/blog/${slug}`); revalidatePath('/blog'); return Response.json({ revalidated: true }); } Кешування та продуктивність
REST API не кешується за замовчуванням. Ми додаємо Redis Object Cache або Nginx-кеш для анонімних запитів. Це знижує TTFB на 30–50% і навантаження на БД у 2 рази. Якщо у вас високі вимоги до швидкості — використовуємо Edge Cache (Cloudflare) з purge по webhook.
Що входить у роботу та терміни
| Етап | Що робимо | Результат |
|---|---|---|
| Аналітика | Розбираємо контентну модель, типи записів, таксономії | Документація з API-специфікацією |
| Налаштування WordPress | CORS, ACF у REST, кастомні ендпоінти, вимкнення фронту | Headless-режим |
| Розробка фронту | API-клієнт, компоненти, ISR, preview mode | Репозиторій з типами та хуками |
| Тестування | Перевірка всіх ендпоінтів, кешування, навантажувальне тестування | Протокол тестування |
| Деплой та передача | Документація з оновлення контенту, доступи, навчання редакторів | Git-репозиторій, README, дамп БД |
- Налаштування headless (CORS, ACF, ендпоінти) — 6–8 годин.
- Інтеграція з Next.js (клієнт, ISR, preview) — 1–1.5 робочих дні.
- Webhook та on-demand revalidation — 3–4 години.
Ми даємо гарантію на код 3 місяці та безкоштовну підтримку після деплою. За 10+ років ми інтегрували WordPress із десятками проєктів — від лендінгів до порталів з мільйонами відвідувачів. Зв'яжіться з нами — оцінимо ваш проєкт за один день.
Порівняння: Headless vs Традиційний WordPress
| Параметр | Headless | Традиційний |
|---|---|---|
| Швидкість завантаження | LCP 1–1.5 с | LCP 2–4 с |
| Гнучкість стеку | Будь-який фреймворк | PHP-шаблони |
| Складність розробки | Вища | Нижча |
| Зручність для редакторів | Звична адмінка | Та ж |
| Підтримка мультиплатформи | Вбудована | Потребує доопрацювання |
| Вартість підтримки | Нижча (менше серверних ресурсів) | Вища (PHP + MySQL) |
Headless WordPress — розумний вибір, коли важлива продуктивність і контроль над фронтендом. Не підходить, якщо бюджет обмежений або немає команди фронтендерів. Отримайте консультацію: ми допоможемо обрати архітектуру та оцінимо ваш проєкт безкоштовно. Замовте інтеграцію — перші результати через 2 дні.







