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
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.
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.
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
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.
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.

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.

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.
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.