add_action('rest_api_init', function () {
register_rest_field('product', 'brand_details', [
'get_callback' => function ($post_array) {
$brand_id = get_post_meta($post_array['id'], 'associated_brand_id', true);
if (!$brand_id) return null;
return [
'name' => get_the_title($brand_id),
'logo' => get_field('brand_logo', $brand_id)['url'] ?? null,
'website' => get_field('brand_website', $brand_id) ?: ''
];
},
'schema' => null,
]);
});Nu vă mai complicați cu GraphQL în WordPress dacă nu aveți un scenariu extrem de complex. Am terminat recent un proiect de e-commerce cu peste 12.000 de produse unde a trebuit să legăm WooCommerce de un frontend în Next.js, folosind custom post types (CPT) pentru specificații tehnice avansate și branduri. Am pornit pe calea clasică cu WPGraphQL, dar ne-am lovit rapid de mari probleme de performanță.
Marea problemă cu WordPress headless nu e să scoți datele, ci să le scoți curate și rapid.
De ce WPGraphQL + ACF ne-a încetinit proiectul
Pe hârtie, WPGraphQL sună perfect. Frontend-iștii își scriu query-urile, cer doar brand_logo și brand_description din ACF, și totul merge brici. În realitate, plugin-ul WPGraphQL for ACF face interogări SQL destul de greoaie în spate. La un trafic de peste 500 de utilizatori concurenți pe catalog, serverul începuse să gâfâie. Timpul de răspuns (TTFB) sărea lejer de 1.2 secunde.
Atunci când WordPress rulează interogări pentru ACF, el face apeluri individuale în tabela wp_postmeta pentru fiecare cheie de câmp, dacă nu ești atent cum le încarci. Când ai zeci de produse într-o buclă, baza de date e îngenuncheată rapid de sute de query-uri mici. În plus, schema generată automat devine uriașă și greu de întreținut. Am decis să facem un pas înapoi și să folosim REST API-ul nativ din WordPress, dar optimizat la sânge.
Optimizarea REST API: Fără gunoi în JSON
Când bifezi „Show in REST” pe un Custom Post Type și pe un grup de câmpuri ACF, WordPress îți aruncă tot istoricul, metadatele inutile și un nod gigant numit acf cu toate valorile posibile. Frontend-ul are nevoie doar de 3 câmpuri pentru cardul de produs, nu de 50.
Am dezactivat expunerea automată ACF în REST și am scris endpoint-uri custom sau am filtrat câmpurile folosind register_rest_field.
Trade-off-ul e evident aici. Pierzi flexibilitatea frontend-ului de a cere exact ce vrea el (avantajul major din GraphQL) și trebuie să scrii cod PHP pentru fiecare entitate nouă. Însă câștigul de performanță e masiv. Am reușit să scădem timpul de răspuns la 80ms folosind Object Cache (Redis) pe endpoint-urile REST customizate, comparativ cu peste 600ms cât scoteam pe GraphQL chiar și cu cache pe query-uri.
Cum înregistrezi un câmp curat
În loc să lași ACF să serializeze tot payload-ul, mai bine înregistrezi manual doar ce ai nevoie în REST API. Codul de mai jos arată cum mapăm doar două câmpuri specifice dintr-un CPT de tip 'brand' direct în răspunsul REST al produsului WooCommerce asociat.
Prin abordarea asta, payload-ul JSON a scăzut de la 45KB pe produs la doar 4KB. Pe o pagină de listare cu 24 de produse, asta înseamnă economie masivă de bandă și procesare mult mai rapidă în Next.js.
Voi ce folosiți pentru proiectele headless cu volum mare de date? Mergeți pe flexibilitatea GraphQL sau preferați controlul și viteza REST-ului nativ?