Інтеграція WP REST API з фронтендом (React/Vue/Next.js)

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Інтеграція WP REST API з фронтендом (React/Vue/Next.js)
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Інтеграція WP REST API з фронтендом (React/Vue/Next.js)

WordPress як headless CMS — робочий підхід для проектів, де потребується нестандартний фронтенд: SPA, мобільний застосунок, статичний сайт з динамічними даними. WP REST API відає дані, React/Vue/Next.js рендерить інтерфейс. Розробка headless-інтеграції від "чистого" Next.js до повнофункціонального production — від 5 до 15 робочих днів залежно від обсягу контенту і складності маршрутизації.

Базова інтеграція: отримання даних

WordPress REST API за замовчуванням доступний за /wp-json/wp/v2/. Отримання останніх постів:

const WP_API_URL = process.env.NEXT_PUBLIC_WP_URL + '/wp-json/wp/v2';

export interface WPPost {
  id: number;
  slug: string;
  title: { rendered: string };
  content: { rendered: string };
  excerpt: { rendered: string };
  date: string;
  featured_media: number;
}

export async function getPosts(params: {
  perPage?: number;
  page?: number;
  category?: number;
  search?: string;
} = {}): Promise<{ posts: WPPost[]; total: number; totalPages: number }> {
  const qs = new URLSearchParams({
    per_page: String(params.perPage ?? 12),
    page:     String(params.page ?? 1),
    _embed:   'wp:featuredmedia,wp:term',
    ...(params.category && { categories: String(params.category) }),
    ...(params.search   && { search: params.search }),
  });

  const res = await fetch(`${WP_API_URL}/posts?${qs}`, {
    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')),
    totalPages: Number(res.headers.get('X-WP-TotalPages')),
  };
}

export async function getPostBySlug(slug: string): Promise<WPPost | null> {
  const res = await fetch(`${WP_API_URL}/posts?slug=${slug}&_embed=wp:featuredmedia,wp:term`);
  const posts = await res.json();
  return posts.length ? posts[0] : null;
}

Next.js App Router: динамічні маршрути

export async function generateStaticParams() {
  const { posts } = await getPosts({ perPage: 100 });
  return posts.map(post => ({ slug: post.slug }));
}

export async function generateMetadata({ params }: { params: { slug: string } }) {
  const post = await getPostBySlug(params.slug);
  if (!post) return {};
  return {
    title:       post.title.rendered,
    description: post.excerpt.rendered.replace(/<[^>]+>/g, '').slice(0, 160),
  };
}

export default async function PostPage({ params }: { params: { slug: string } }) {
  const post = await getPostBySlug(params.slug);
  if (!post) notFound();

  return (
    <article className="post-single">
      <h1 dangerouslySetInnerHTML={{ __html: post.title.rendered }} />
      <div
        className="post-content"
        dangerouslySetInnerHTML={{ __html: post.content.rendered }}
      />
    </article>
  );
}

Користувацький хук для React SPA

import useSWR from 'swr';

const fetcher = (url: string) => fetch(url).then(r => r.json());

export function usePosts(category?: string, page = 1) {
  const params = new URLSearchParams({ per_page: '12', page: String(page), _embed: '1' });
  if (category) params.set('categories', category);

  const { data, error, isLoading } = useSWR<WPPost[]>(
    `/wp-json/wp/v2/posts?${params}`,
    fetcher,
    { revalidateOnFocus: false }
  );

  return { posts: data ?? [], isLoading, error };
}

GraphQL через WPGraphQL

WPGraphQL — плагін, що додає GraphQL-енпоінт. Для складних сторінок з вкладеними даними GraphQL вигідніший за REST: один запит замість кількох:

query GetProjectWithRelated($slug: String!) {
  projectBy(slug: $slug) {
    id
    title
    content
    featuredImage {
      node { sourceUrl altText }
    }
  }
}

On-demand ISR при публікації у WordPress

Next.js підтримує on-demand revalidation — перестройку сторінок при змінені даних у CMS:

add_action('save_post', function (int $post_id, WP_Post $post): void {
    if ($post->post_status !== 'publish') return;

    $next_url = get_option('nextjs_revalidate_url');
    $secret   = get_option('nextjs_revalidate_secret');

    if (!$next_url || !$secret) return;

    wp_remote_post("{$next_url}/api/revalidate", [
        'body'    => json_encode([
            'secret' => $secret,
            'path'   => '/' . $post->post_type . '/' . $post->post_name,
        ]),
        'headers' => ['Content-Type' => 'application/json'],
        'blocking'=> false,
    ]);
}, 10, 2);
export async function POST(req: Request) {
  const { secret, path } = await req.json();

  if (secret !== process.env.REVALIDATE_SECRET) {
    return Response.json({ error: 'Invalid secret' }, { status: 401 });
  }

  revalidatePath(path);
  return Response.json({ revalidated: true, path });
}

CORS для headless

WordPress і Next.js на різних доменах потребують CORS-настройки:

add_action('rest_api_init', function () {
    remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
    add_filter('rest_pre_serve_request', function ($value) {
        $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
        $allowed = ['https://mysite.com', 'http://localhost:3000'];
        if (in_array($origin, $allowed)) {
            header('Access-Control-Allow-Origin: ' . $origin);
            header('Access-Control-Allow-Credentials: true');
            header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
            header('Access-Control-Allow-Headers: Authorization, Content-Type');
        }
        return $value;
    });
});

Продуктивність: що кешувати

Дані Стратегія
Список постів ISR, revalidate: 60s
Окремий пост ISR + on-demand revalidate
Меню навігації Static (revalidate: false)
Результати пошуку SSR (без кеша, параметри змінюються)
ACF-поля налаштувань Static або revalidate: 3600s

Headless WordPress — це архітектурний вибір, не просто настройка плагіна. Розробка фронтенду, настройка WordPress і розгортання двох незалежних застосунків суммуються в вагомий обсяг роботи, який потрібно закладати в оцінку заранее.