Przejdź do treści
Wszystkie projekty

01Portfolio

WirePress — headless WordPress + Next.js

Wtyczka, która robi z WordPressa backend treści dla frontendu w Next.js: podpisane webhooki, kolejka w tle, podgląd szkiców na froncie i cache GraphQL serwowany, zanim WordPress wstanie. Strona statyczna odpowiada ok. 35× szybciej niż klasyczny WordPress.

W liczbach

Szybciej niż klasyczny WordPress
~35×
Zapytanie GraphQL z cache
230 → 7 ms
Testy wtyczki i frontendu
133
01

Problem

WordPress w roli headless CMS ma dwa słabe punkty. Jeśli webhooki wychodzą w trakcie zapisu, wolny albo niedostępny frontend spowalnia panel redaktora — zmierzyłem 20,4 s na jedno żądanie. A jeśli webhook niesie treść, jedno zgubione powiadomienie zostawia na stronie starą wersję na zawsze. Do tego redaktor traci podgląd szkicu, a samo wstawanie WordPressa to ok. jednej trzeciej czasu odpowiedzi — dolna granica dla każdej optymalizacji w jego środku.

02

Podejście

Rozdzieliłem dwa kanały: treść frontend pobiera sam przez WPGraphQL, a webhook niesie tylko gotowe ścieżki i tagi cache do unieważnienia, podpisane HMAC-SHA256 osobnym kluczem każdego frontendu. Wszystkie zmiany z jednego żądania trafiają do kolejki jako jeden ładunek; wysyła je WP-Cron z ponawianiem po 1, 5 i 15 minutach, więc panel odpowiada od razu. Powtórzone zapytania GraphQL obsługuje drop-in advanced-cache.php, który czyta zapisaną odpowiedź, zanim załaduje się rdzeń, wtyczki i motyw. Po stronie Next.js 16 strony są statyczne i odświeżane punktowo przez revalidateTag i revalidatePath, a przy budowaniu treść jest pobierana paczkami po 100 zamiast pytać o każdą stronę osobno. Redaktor ma w panelu kolejkę z kodami błędów, test połączenia, rotację kluczy i podgląd szkiców w prawdziwym szablonie frontu.

03

Efekt

Wersja 2.0.0, pomiary z wbudowanego symulatora (316 wpisów z obrazkami, jedna maszyna): strona statyczna p50 13 ms wobec 451 ms klasycznego WordPressa, trasa renderowana na żądanie 1213 → 53 ms, powtórzone zapytanie GraphQL 230 → 7 ms, zapytania przy budowaniu 355 → 47, pełny build 343 stron w 25 s. Zmiana z panelu jest na froncie po 1,4–5 s, a niedostępny frontend nie spowalnia WordPressa (20,4 s → 0,35 s na żądanie). Całość pokrywa 96 testów wtyczki (215 asercji) i 37 testów end-to-end frontendu.

Jak to działa

  1. 01

    Treść i powiadomienie to dwa kanały

    Frontend pobiera treść sam przez GraphQL, a webhook mówi tylko, co jest nieaktualne. Zgubione powiadomienie nie zostawia starej strony na zawsze — źródłem prawdy zawsze jest WordPress.

  2. 02

    Kolejka, która nie blokuje redaktora

    Zmiany z jednego zapisu trafiają do kolejki jako jeden ładunek, a wysyła je WP-Cron. Nieudane próby wracają po 1, 5 i 15 minutach; panel pokazuje kod HTTP i treść błędu, a „Ponów” wysyła jeszcze raz.

    Kolejka, która nie blokuje redaktora
  3. 03

    Gotowe ścieżki i tagi cache

    Szablony w rodzaju /blog/{slug} zamieniają zmianę w konkretne adresy do odświeżenia. Frontend niczego nie mapuje — sprawdza podpis HMAC i woła revalidatePath oraz revalidateTag.

    Gotowe ścieżki i tagi cache
  4. 04

    Cache GraphQL, zanim WordPress wstanie

    Drop-in advanced-cache.php odpowiada z pliku na powtórzone zapytanie i kończy żądanie przed startem rdzenia. Pomija zalogowanych użytkowników, mutacje i odpowiedzi z błędami, a zapis jest atomowy. Efekt: 230 ms → 7 ms.

  5. 05

    Podgląd szkiców na froncie

    Przycisk „Podgląd” otwiera Next.js z niepublikowaną treścią w prawdziwym szablonie, bez JWT i haseł aplikacji. Token jest ważny godzinę, a strona podglądu ma noindex.

Napisz