Headless WordPress setup’ında data katmanını WP REST API veya WPGraphQL plugin arasında seçmek proje hızını ve bakımını etkiliyor.
2 projede REST, 1 projede GraphQL kullandım. Ortaklıklar, farklılıklar, karar kriterleri üzerine notlar.
WP REST API’nin temel durumu
WP 4.7’den beri core’da. Kurulum gerektirmiyor. Endpoint’ler:
GET /wp-json/wp/v2/posts– post listesiGET /wp-json/wp/v2/posts/{id}– tek postGET /wp-json/wp/v2/pages– page’lerGET /wp-json/wp/v2/categories– kategorilerGET /wp-json/wp/v2/users/{id}– kullanıcıPOST /wp-json/wp/v2/posts– post yarat (auth gerekli)
Custom post type’ınız varsa:
register_post_type('product', [
'show_in_rest' => true,
'rest_base' => 'products'
]);Endpoint: /wp-json/wp/v2/products
REST API’nin güçlü yanları
Built-in, zero setup. Plugin yok, kurulum yok. WP her versiyonunda var.
RESTful pattern’ler. CRUD operations URL-driven. Cache’leme HTTP-native (ETag, Cache-Control).
Authentication flexibility. App Password, JWT plugin, OAuth plugin seçenekleri.
Consumer tooling. REST pek çok framework, Postman’de native.
Learning curve düşük. Her developer REST biliyor.
REST API’nin sınırlamaları
Over-fetching. Post listesi için tüm field’lar geliyor, sadece title+url istiyorum diyen API yok. _fields parameter ile sınırlandırılabiliyor ama limited.
Multiple request. Post + author + category ilişkisi için 3 endpoint çağrılıyor. Post’ta _embed parameter ile author/featured_media embed edilebiliyor, ama complex nested query’ler için yetmez.
Custom field exposure. ACF field’larını default exposure etmiyor. Her field için register_rest_field ile ek kod.
Filtering limited. Meta query REST’te direct değil, custom filter register etmeyi gerektiriyor.
WPGraphQL plugin
WPGraphQL WordPress için GraphQL endpoint ekleyen plugin. WordPress schema’sını GraphQL type’a mapliyor.
Kurulum:
- Plugin install (wordpress.org’dan WPGraphQL veya composer)
- Activate
- Endpoint:
/graphqldirekt available - GraphiQL interface admin’de (debugging için)
Query example:
query GetPost($slug: String!) {
postBy(slug: $slug) {
title
content
author {
node {
name
avatar {
url
}
}
}
categories {
nodes {
name
slug
}
}
featuredImage {
node {
sourceUrl
altText
}
}
}
}Tek request’te post + author + categories + featured image. REST’te 4 request gerekirdi.
GraphQL’in güçlü yanları
Single request, multi-resource. Nested query ile tek HTTP round trip.
Field selection. Client istediği field’ı seçiyor, server başkasını göndermiyor. Payload küçük.
Type safety. Schema’dan TypeScript/other language type generation. IDE autocompletion güçlü.
ACF support. WPGraphQL for ACF extension ile tüm ACF field’lar GraphQL schema’ya eklenir.
Subscriptions. Real-time update’ler mümkün (ama rare use case).
Developer experience. GraphiQL ile schema exploration, query testing.
GraphQL’in zorlukları
Plugin dependency. WPGraphQL bir 3rd party plugin, core değil. Maintainer community destekli ama commercial support yok. Plugin’in maintainer’ı durursa risk.
Learning curve. GraphQL’e alışkın olmayan team için extra öğrenme.
Caching complex. HTTP cache GraphQL’de doğal değil, tek endpoint + POST request. CDN cache zor. Application-level cache gerekli (Apollo, urql).
Schema maintenance. Custom field eklediğinde GraphQL type’ı register etmek gerekiyor. WPGraphQL otomatik exposure etmiyor.
Error handling. GraphQL error’lar 200 OK response’da geliyor (error array ile). Status-based error handling çalışmıyor.
Performans karşılaştırma
Aynı dataset üzerinde test:
Scenario: blog post + 3 related post + author + category.
REST API:
– 5 request
– Total transfer: 48 KB
– Round-trip latency (3G): 1.8 saniye
GraphQL:
– 1 request
– Total transfer: 12 KB (field selection ile)
– Round-trip latency (3G): 450 ms
Mobile veya slow network’te GraphQL açık kazanç.
Desktop / fast network’te fark azalıyor.
Next.js’te implementation
REST API ile:
export async function getStaticProps({ params }) {
const [post, categories, author] = await Promise.all([
fetch(`${WP_URL}/wp-json/wp/v2/posts?slug=${params.slug}`).then(r => r.json()),
fetch(`${WP_URL}/wp-json/wp/v2/categories`).then(r => r.json()),
fetch(`${WP_URL}/wp-json/wp/v2/users/${post.author}`).then(r => r.json())
]);
return { props: { post: post[0], categories, author } };
}GraphQL ile:
import { GraphQLClient } from 'graphql-request';
const client = new GraphQLClient(`${WP_URL}/graphql`);
export async function getStaticProps({ params }) {
const query = `
query($slug: String!) {
postBy(slug: $slug) {
title
content
author { node { name } }
categories { nodes { name slug } }
}
}
`;
const data = await client.request(query, { slug: params.slug });
return { props: { post: data.postBy } };
}GraphQL daha compact, type generation avantajı frontend’e yansıyor.
TypeScript + codegen
WPGraphQL + GraphQL Code Generator ile otomatik TS type üretimi:
npx graphql-codegen --config codegen.ymlcodegen.yml:
schema: https://your-wp.com/graphql
documents: './src/**/*.graphql'
generates:
./src/generated/types.ts:
plugins:
- typescript
- typescript-operationsFrontend’de:
import { GetPostQuery } from './generated/types';
const data: GetPostQuery = await client.request(query);
console.log(data.postBy.title); // fully typedREST API’de manuel type yazmak gerekiyor veya OpenAPI spec tanımlamak.
Hangi durumda hangisi?
REST API tercih edilecek durumlar:
- Küçük proje, hızlı setup
- Team GraphQL’e alışkın değil
- Public API consumer’ları için (daha geniş tooling)
- Cache-heavy use case (HTTP cache)
- WPGraphQL plugin dependency istenmiyor
GraphQL tercih edilecek durumlar:
- Mobile-first, network-sensitive
- Complex nested data queries
- TypeScript frontend
- Custom fields (ACF) heavy
- Developer experience priority
Authentication
Headless setup’ta authentication 2 case:
Read-only public content: no auth gerekli. Post, page, product publicly readable.
Write operations (comment, form submit, user data): auth gerekli.
REST API:
– Application passwords (WP 5.6+ core feature)
– JWT plugin
– OAuth2 plugin
GraphQL:
– WPGraphQL supports same auth methods
– Request header’da credentials
JWT genelde headless için en clean. Bearer token, stateless, frontend friendly.
Cache stratejisi
REST API + CDN:
Cache-Control: public, max-age=300response header (Nginx/plugin ile)- CDN edge cache
- Post update olunca
/wp-json/wp/v2/posts/{id}endpoint’i purge
GraphQL + Apollo/urql client cache:
- Server-side: WPGraphQL Smart Cache plugin (internal cache)
- Client-side: Apollo Cache veya urql cache
- Next.js’te: ISR ile regenerate (request-by-request cache invalidation değil, time-based)
REST’in HTTP-native cache yaklaşımı GraphQL’de yok. Cache invalidation daha custom.
Maintenance comparison
6-12 aylık proje maintenance:
REST API: WP major upgrade’lerde endpoint stable, breaking change rare. ACF REST exposure’ı her field için maintain edilmeli.
GraphQL: WPGraphQL plugin’in uyumluluk kontrolü. Custom type register etmek maintenance.
Her ikisi de manageable, ama GraphQL bir bit daha ceremony.
Son tavsiye
Yeni headless WP projede karar matrisi:
- Hızlı prototype: REST
- Production SaaS / mobile: GraphQL
- Public API exposure: REST
- ACF-heavy, complex schema: GraphQL
- Cache-critical: REST
- TypeScript-first: GraphQL
Her ikisinin de artısı eksiği var, “biri doğru diğeri yanlış” değil. Projenin doğasına göre seçim.
Benim pattern: küçük-orta projelerde REST yeter, büyük/complex projelerde GraphQL yatırımı değer veriyor.