Headless WordPress-revolusjonen har modnet. I 2026 handler spørsmålet ikke lenger om hvorvidt du bør koble fra frontenden, men hvordan du bør hente dataene dine. Valget står mellom det innebygde REST API-et i WordPress-kjernen og GraphQL, som på WordPress nesten alltid betyr utvidelsen WPGraphQL.
Avgjørelsen hviler nå på tekniske krav du kan måle: hvor mange forespørsler en side trenger, hvor mye JSON nettleseren må tolke, hvordan svarene mellomlagres på edge, hvordan frontenden får typene sine, og hvem som vedlikeholder den ekstra koden. Begge alternativene er modne. Denne guiden sammenligner dem på disse punktene, og hvert API-navn, hver innstilling og hver standardverdi er sjekket mot REST API Handbook og WPGraphQL-dokumentasjonen.
1. Forskjeller mellom REST API og GraphQL i WordPress
REST (endpoint-driven)
GET /wp-json/wp/v2/posts/101
GET /wp-json/wp/v2/users/4
GET /wp-json/wp/v2/categories?post=101
= several HTTP requests, each with a fixed response shape
GraphQL (document-driven)
POST /graphql
query SinglePost {
post(id: "101", idType: DATABASE_ID) {
title
date
author { node { name } }
categories { nodes { name slug } }
}
}
= one HTTP request, the client names every field it wantsREST API-et er bygd på faste ressurser. En forespørsel til /wp-json/wp/v2/posts returnerer hele representasjonen av innlegget: rendret innhold, utdrag, GUID, kommentarstatus, lenker og mer. WPGraphQL snur dette. Klienten sender et query-dokument, og serveren returnerer bare feltene som dokumentet nevner.
Over-fetching og under-fetching i REST API-et
WPGraphQL-teamet beskriver REST-problemet som over-fetching og under-fetching på samme tid: posts-endpointet returnerer kategori-ID-er, tagg-ID-er, innhold og utdrag som en listevisning ikke trenger, men mangler likevel forfatternavn og avatar, som krever flere forespørsler (WPGraphQL vs WP REST API).
Kjernen har to svar på dette, og de blir ofte oversett. Den globale parameteren _fields returnerer bare et utvalg av feltene, for eksempel ?_fields=id,title,link, og siden WordPress 5.3 støtter den nestede egenskaper som én enkelt meta-nøkkel. Parameteren _embed tar med lenkede ressurser (forfatter, fremhevet bilde, termer) i samme svar, og siden WordPress 5.4 kan du begrense den til bestemte lenkerelasjoner (Global parameters). Med begge kan en REST-listevisning komme nær en GraphQL-payload. Det REST fortsatt mangler, er et typet schema som klienten kan spørre mot.
2. Fordeler og ulemper med WordPress REST API
WordPress REST API har vært en del av kjernen i ti år, og det er mer robust enn noen gang.
- Styrken: Det fungerer med en gang. Ingen ekstra utvidelser er nødvendig for grunnleggende funksjonalitet. Det er svært enkelt å mellomlagre (cache) på HTTP-nivå via standard CDN-er, fordi hver ressurs har sin egen URL.
- Svakheten: Over-fetching som standard. Hvis du bare trenger tittel og slug for et innlegg og glemmer
_fields, sender REST hele innleggsobjektet, inkludert innhold og metadata. Dette kaster bort båndbredde, spesielt på mobil.
REST API-et bruker JSON for forespørsler og svar, og alle språk som kan sende HTTP-forespørsler og lese JSON, kan bruke det (REST API Handbook). Derfor snakker nesten alle integrasjonsplattformer, CRM-koblinger og webhook-mottakere REST først.
3. Fordeler og ulemper med WPGraphQL
GraphQL (som regel implementert via WPGraphQL) lar frontend-utvikleren bestemme hvordan svaret skal se ut.
- Styrken: Én forespørsel, nøyaktig de dataene du vil ha. Du kan hente et innlegg, kategoriene, forfatterens tre siste innlegg og nettstedsinnstillingene i én enkelt runde til serveren. Schemaet er sterkt typet, og hvert felt oppgir sin type.
- Svakheten: Det krever en ekstra utvidelse som må vedlikeholdes. Komplekse spørringer kan noen ganger føre til trege databaseoppslag hvis de ikke er optimalisert med object cache (Redis).
Fakta om utvidelsen, lest fra wordpress.org-katalogen 14. oktober 2026: WPGraphQL 2.24.0, krever WordPress 6.0 og PHP 7.4, testet opp til WordPress 7.0.7, mer enn 30 000 aktive installasjoner. Utvidelsessiden opplyser at WPGraphQL er i ferd med å bli en Canonical Plugin på WordPress.org. Den følger Semantic Versioning, så et hopp i hovedversjon varsler endringer som bryter kompatibilitet, og det lønner seg å lese release notes før du oppdaterer.
4. Hvordan WPGraphQL løser N+1-problemet
En naiv resolver for “de siste 20 innleggene og navnet på hver forfatter” kjører én spørring for innleggene og deretter én spørring per forfatter. Det er N+1-problemet. WPGraphQL unngår det med DataLoader-mønsteret: under oppløsningen samler den ID-ene den trenger (for eksempel alle post_author-verdier) og laster dem i én batch. I WPGraphQL-dokumentasjonens eget eksempel faller SQL-spørringene for forfatterne til fem innlegg fra fem til én (WPGraphQL vs WP REST API).
SELECT * FROM wp_users WHERE ID IN (2, 5, 8, 14);I tillegg har WPGraphQL et Model Layer: et sett PHP-klasser som pakker inn WordPress-objekter og sjekker sensitive felt, som en brukers e-postadresse, før de returneres (WPGraphQL concepts).
Hvordan utvide WPGraphQL-schemaet i PHP
<?php
declare(strict_types=1);
add_action('graphql_register_types', function (): void {
register_graphql_object_type('PerformanceMetrics', [
'description' => __('Measured Core Web Vitals for a post', 'wppoland'),
'fields' => [
'lcpSeconds' => ['type' => 'Float'],
'inpMilliseconds' => ['type' => 'Int'],
'clsScore' => ['type' => 'Float'],
],
]);
register_graphql_field('Post', 'cwvMetrics', [
'type' => 'PerformanceMetrics',
'resolve' => function ($post): ?array {
$raw = get_post_meta($post->databaseId, '_wppoland_cwv_data', true);
if (!is_array($raw)) {
return null;
}
return [
'lcpSeconds' => isset($raw['lcp']) ? (float) $raw['lcp'] : null,
'inpMilliseconds' => isset($raw['inp']) ? (int) $raw['inp'] : null,
'clsScore' => isset($raw['cls']) ? (float) $raw['cls'] : null,
];
},
]);
});5. Hvordan lage et eget REST-endpoint i WordPress
Grunnmønsteret er register_rest_route() på hooken rest_api_init, eller en klasse som utvider WP_REST_Controller. Reglene fra håndboken som betyr noe i produksjon (Adding custom endpoints):
- Siden WordPress 5.5 utløser en rute registrert uten
permission_callbacket_doing_it_wrong-varsel. For et offentlig endpoint sender du__return_trueeksplisitt. - Navnerom bør følge mønsteret
vendor/v1, og versjonen økes når du bryter kompatibiliteten. - Feil er en
WP_Errormed HTTP-koden satt i nøkkelenstatusi dataene, for eksempel400ved ugyldig input. - Når du pakker inn en eksisterende callback, kjører du returverdien gjennom
rest_ensure_response().
<?php
declare(strict_types=1);
class Wppoland_Metrics_Controller extends WP_REST_Controller
{
protected $namespace = 'wppoland/v1';
protected $rest_base = 'metrics';
public function register_routes(): void
{
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<id>\d+)', [
[
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_item'],
'permission_callback' => '__return_true',
'args' => [
'id' => ['type' => 'integer', 'required' => true],
],
],
'schema' => [$this, 'get_public_item_schema'],
]);
}
public function get_item($request)
{
$post = get_post((int) $request['id']);
if (!$post || $post->post_status !== 'publish') {
return new WP_Error('rest_post_invalid_id', __('Not found.', 'wppoland'), ['status' => 404]);
}
return rest_ensure_response([
'id' => $post->ID,
'title' => get_the_title($post),
]);
}
public function get_item_schema(): array
{
return [
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'wppoland_metrics',
'type' => 'object',
'properties' => [
'id' => ['type' => 'integer'],
'title' => ['type' => 'string'],
],
];
}
}
add_action('rest_api_init', function (): void {
(new Wppoland_Metrics_Controller())->register_routes();
});Egenskapene er bevisst deklarert uten type: WP_REST_Controller deklarerer $namespace og $rest_base uten type, og PHP avviser en typet omdeklarering i en barneklasse. Hele gjennomgangen av controlleren finner du i guiden vår om egne REST API-endpoints.
6. Er GraphQL raskere enn REST i WordPress
I 2026 handler ytelse om mer enn bare fart, det handler om effektivitet.
- Nettverksforsinkelse (latency): GraphQL vinner på komplekse sider. Ved å samle flere datapunkter i én forespørsel fjerner det rundturene etter hverandre som en REST-side med innlegg, forfatter, termer og relaterte innlegg trenger.
- Caching-strategi: REST vinner på brukervennlighet. Siden hvert endpoint har en unik URL, kan du mellomlagre det globalt på Cloudflare med liten innsats. GraphQL trenger GET-forespørsler eller persisted queries for å oppnå tilsvarende resultater på edge.
- Server-CPU: REST er som regel lettere for én enkel ressurs. GraphQL må tolke og validere query-dokumentet før det løser opp noe som helst, og derfor betyr object cache mer på et GraphQL-nettsted.
WPGraphQL-teamet har publisert én måling: å hente 100 innlegg tok 335 kb og 7,91 s fra REST-endpointet mot 6,4 kb og 67 ms fra WPGraphQL (WPGraphQL vs WP REST API). Se på det som leverandørens egen test med standard REST-output. En REST-forespørsel med _fields tetter mye av forskjellen i payload, så mål dine egne sider før du velger ut fra dette argumentet alene.
7. Hvordan cache GraphQL på CDN med persisted queries
GraphQL-spørringer sendes vanligvis som HTTP POST med spørringen i body, og et CDN cacher ikke POST etter URL. WPGraphQL sier selv at POST er den vanlige metoden og at GET har begrenset støtte (Interacting with WPGraphQL). Edge-caching håndteres av tilleggsutvidelsen WPGraphQL Smart Cache (versjon 2.3.3, mer enn 6 000 aktive installasjoner, nå en del av WPGraphQL-monorepoet, ifølge utvidelsessiden).
Slik fungerer det ifølge Smart Cache-dokumentasjonen:
- Network cache: for å dra nytte av den sender du HTTP GET-forespørsler for offentlige data. Svarene har en
X-GraphQL-Keys-header med tagger for alt spørringen berørte. Når innhold endres, sender Smart Cache purge-hendelser, og verten fjerner de mellomlagrede dokumentene som er tagget med disse nøklene. Guiden nevner WP Engine og Pantheon som verter med støtte. Standardmax-ageer 600 sekunder og kan justeres i utvidelsens Cache-innstillinger (Network cache). - Persisted queries: et query-dokument lagres på serveren i en ikke-offentlig posttype,
graphql_document, og refereres med en query-ID. Dokumentets slug er SHA-256-hashen av spørringen, og en klient kan bare registrere en nyqueryIdhvis den stemmer med denne hashen. Klienter sender deretter korte GET-forespørsler som?queryId=getPostById&variables={...}. Utvidelsen fungerer med Apollo Persisted Query Link (Persisted queries). - Tillatelses- og blokkeringslister: under innstillingene for lagrede spørringer velger du mellom et helt offentlig endpoint, å tillate bare bestemte lagrede spørringer, eller å blokkere bestemte spørringer. Brukere med
manage_optionser unntatt.
Med GET-forespørsler, persisted queries og tag-basert purging på plass mellomlagres et GraphQL-svar på edge omtrent som en REST-URL. Uten dem faller GraphQL-caching tilbake på object cache i WordPress.
8. WordPress REST batch API vs. batching i GraphQL
WordPress 5.6 la til et batch-rammeverk på /wp-json/batch/v1. Det tar imot én POST med flere underforespørsler, 25 som standard (filteret rest_get_max_batch_size). GET-forespørsler støttes ikke, så det er ment for skriveoperasjoner, og hver rute må aktivere det med allow_batch når den registreres. Modusen require-all-validate avviser hele batchen hvis én forespørsel feiler valideringen (REST API batch framework in WordPress 5.6).
Begrensninger ved batching i REST API-et
- Ingen sammensetning av data: underforespørslene kjøres som separate operasjoner. Du kan ikke sende resultatet av forespørsel A (en forfatter-ID) videre til forespørsel B i samme batch.
- Laget for skriving: uten GET hjelper batch-endpointet ikke en lesetung frontend i det hele tatt.
- Kan ikke caches på edge: det er en POST, så et CDN sender hver batch videre til origin.
GraphQL løser opp relaterte data i én spørring av natur, og WPGraphQL tar også imot spørringer i batch. Sikkerhetsdokumentasjonen nevner at du kan begrense eller slå av batch-spørringer på GraphQL-innstillingssiden.
9. Grenser for paginering i REST og GraphQL
REST API-et begrenser per_page til 100 poster og returnerer to headere med hver samling: X-WP-Total (totalt antall poster) og X-WP-TotalPages (totalt antall sider) (Pagination). En klient som trenger 450 innlegg, sender fem forespørsler.
WPGraphQL bruker markørbaserte connections (first, after, pageInfo { hasNextPage endCursor }). Det begrenser antall elementer per connection-side til 100 for de fleste connections, og filteret graphql_connection_max_query_amount endrer denne grensen (WPGraphQL security). Hev den bare sammen med dybdegrensen og caching, fordi større sider gjør dyre spørringer billigere å sende.
10. Autentisering i WordPress REST API og WPGraphQL
REST API-et har to innebygde metoder (Authentication):
- Cookie-autentisering for kode som kjører i det innloggede kontrollpanelet. En manuell forespørsel må sende en nonce for handlingen
wp_rest, vanligvis i headerenX-WP-Nonce. Uten noncen behandles forespørselen som uautentisert, selv om brukeren er logget inn. - Application Passwords, del av kjernen siden WordPress 5.6. De bruker Basic Auth og fungerer bare over HTTPS.
WPGraphQL følger rettighetene i WordPress: alt WordPress viser offentlig, er offentlig i GraphQL, og data som krever autentisering i WordPress, krever en autentisert GraphQL-forespørsel. Brukere uten publiserte innlegg holdes utenfor offentlige brukerspørringer, og felt som en brukers e-post krever spesifikk tillatelse (WPGraphQL security). Tokenbaserte innloggingsflyter (JWT og lignende) kommer fra utvidelser, ikke fra selve kjerneutvidelsen.
11. Hvordan sikre REST API og GraphQL i WordPress
| Tiltak | WPGraphQL | REST API |
|---|---|---|
| Oppdagelse av schema | Offentlig introspection er slått av som standard; slå den på i GraphQL-innstillingene bare hvis du trenger den | Indeksen /wp-json/ lister rutene; krev autentisering med rest_authentication_errors hvis nettstedet ikke har offentlige konsumenter |
| Spørringsdybde | Nye installasjoner begrenser dybden til 15; filteret graphql_query_depth_max | Ikke relevant, svarformen er fast per endpoint |
| Spørringskostnad | Kostnadsbaserte kompleksitetsgrenser finnes ikke i utvidelsen ennå (fulgt opp i issue #3922) | Ikke relevant |
| Sidestørrelse | 100 elementer per connection-side som standard | per_page begrenset til 100 |
| Batching | Batch-spørringer kan begrenses eller slås av | Ruter må aktivere det med allow_batch |
| Autentisering ved skriving | Rettigheter i WordPress; tokens via utvidelser | Cookie pluss nonce, eller Application Passwords over HTTPS |
Kilder: WPGraphQL security, REST API Handbook FAQ. Håndbokens måte å blokkere anonym REST-tilgang på er en is_user_logged_in()-sjekk på filteret rest_authentication_errors. Rate limiting hører hjemme på edge (WAF eller CDN) for begge API-ene, fordi verken utvidelsen eller kjernen har det innebygd.
12. Generere TypeScript-typer fra WPGraphQL
Fordi GraphQL-schemaet er typet og støtter introspection, kan verktøy som GraphQL Code Generator lese schemaet og frontendens spørringer og generere TypeScript-typer for hvert spørringsresultat. Et felt som blir nullable eller forsvinner fra schemaet, feiler da typesjekken i editoren og i CI, før det når produksjon.
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
import { print } from 'graphql';
export async function executeGraphQL<TData, TVariables>(
document: TypedDocumentNode<TData, TVariables>,
variables?: TVariables
): Promise<TData> {
const response = await fetch(import.meta.env.WP_GRAPHQL_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: print(document), variables }),
});
if (!response.ok) throw new Error(`GraphQL HTTP ${response.status}`);
const { data, errors } = await response.json();
if (errors?.length) throw new Error(errors[0].message);
return data;
}REST API-et publiserer et JSON Schema for hver rute, så typer kan genereres der også, men du setter dem sammen per endpoint, og serveren validerer ikke feltutvalget klienten din gjør.
13. Feilhåndtering i REST API og GraphQL
En REST-feil er en WP_Error serialisert som JSON med code, message og data.status, og HTTP-statusen i svaret samsvarer med data.status. Hvis forespørselen feiler, er hele svaret en feil. Det er forutsigbart for overvåking, men en side bygd fra ett REST-kall kan ikke vise halvparten av dataene sine.
GraphQL kan returnere delvise data. Svaret har både data og errors, og hver feil har en path som peker på feltet som feilet:
{
"data": { "post": { "title": "Headless WordPress architecture", "relatedPosts": null } },
"errors": [
{ "message": "Internal server error", "path": ["post", "relatedPosts"] }
]
}Frontenden kan vise artikkelen og bare vise en reserveløsning for blokken som feilet. Baksiden: en GraphQL-forespørsel som delvis feilet, returnerer likevel HTTP 200, så overvåkingen må lese errors-listen, ikke bare statuskoder.
14. GraphQL-mutasjoner og optimistisk UI i WordPress
Skriving i GraphQL skjer med mutasjoner. En mutasjon endrer data og returnerer det oppdaterte objektet i samme svar, slik at klienten kan oppdatere sin lokale tilstand uten en ny forespørsel. WPGraphQL-kjernen har mutasjoner for innlegg, termer, brukere og kommentarer, for eksempel createComment:
mutation AddComment($input: CreateCommentInput!) {
createComment(input: $input) {
success
comment { id content date }
}
}Det gjør optimistisk UI enkelt: grensesnittet viser den nye kommentaren med en gang og ruller bare tilbake hvis mutasjonen returnerer en feil. Mutasjoner for WooCommerce-handlekurven er ikke en del av WPGraphQL-kjernen; de kommer fra en egen utvidelse. Med REST er den samme flyten en POST etterfulgt av lesing av ressursen som returneres, og det fungerer like godt for enkeltstående skriveoperasjoner.
15. GraphQL eller REST for AI-agenter og Abilities API
AI-agenter og MCP-klienter er nå vanlige API-konsumenter. GraphQL introspection lar en agent lese schemaet og se hvilke typer og argumenter som finnes, men WPGraphQL har offentlig introspection slått av som standard, så en agent trenger autentisert tilgang eller et eksportert schema.
WordPress-kjernen valgte en annen vei. Abilities API, i kjernen siden WordPress 6.9 (2. desember 2025), registrerer operasjoner med et schema for input og output, en permission callback og en execute callback, og eksponerer dem via REST-endpointene wp-abilities/v1 og MCP Adapter (Abilities API in WordPress 6.9). For agenter som handler på et nettsted, er dette REST-baserte laget den innebygde veien. Mer om dette i guiden vår om WordPress Abilities API.
16. Teste WordPress API med GraphiQL og Postman
- REST: Kjent for nesten alle utviklere. Du kan teste endpoints i en nettleser eller i verktøy som Postman umiddelbart. Legg til
?_envelopenår en klient ikke kan lese headere: svaret har da headere og statuskode i body. - GraphQL: WPGraphQL leveres med GraphiQL, en IDE i nettleseren inne i WordPress-adminpanelet som lar deg utforske hele schemaet, se tilgjengelige felt og teste spørringer og mutasjoner med autofullføring. For frontend-team er dette et reelt produktivitetsløft.
For å unngå regresjoner bør du sammenligne frontendens spørringer med schemaet i CI ved hver merge, slik at et felt som er fjernet eller har fått ny type, stopper bygget. På REST-siden validerer du svarene mot JSON Schema for hver rute.
17. Hvordan migrere fra REST API til WPGraphQL uten nedetid
- Sameksistens: installer WPGraphQL på staging med
wp plugin install wp-graphql --activateog koble hver egendefinerte posttype og taksonomi inn i schemaet. REST fortsetter å betjene produksjon. - Skrivebeskyttede sider først: flytt arkiv- og listesider til GraphQL-spørringer med genererte typer, og sammenlign payload og responstid med REST-versjonen.
- Detaljsider og caching: flytt enkeltvisninger, og legg deretter til Smart Cache med GET-forespørsler eller persisted queries hvis verten din støtter network cache.
- Rydd opp i REST-eksponeringen: behold REST-rutene som webhooks, automatiseringer og integrasjoner bruker, og krev autentisering der ingen offentlig konsument er igjen.
18. REST API og GraphQL sammenlignet i tabell
| Funksjon | REST API | GraphQL (WPGraphQL) |
|---|---|---|
| Oppsett | Innebygd | Krever utvidelse |
| Datahenting | Faste endpoints | Fleksibel, definert av klienten |
| Over-fetching | Standard, reduseres med _fields | Unngås av spørringen |
| Relaterte data | Ekstra forespørsler eller _embed | Én spørring |
| Caching | Enkelt (URL-basert) | GET-forespørsler eller persisted queries |
| Typing | JSON Schema per rute, ikke håndhevet på klienten | Sterkt typet schema |
| Grense for sidestørrelse | 100 per side | 100 per connection-side |
| Ideelt for | Enkle apper, webhooks, integrasjoner | Komplekse JS-apper, headless |
Når bør du bruke GraphQL i stedet for REST i WordPress
Hvis du bygger et moderne, frakoblet nettsted med React, Astro eller Next.js, passer GraphQL som regel best. Muligheten til å be om nøyaktig det som trengs, med genererte typer, gir en slankere og mer vedlikeholdsvennlig frontend.
Likevel bør du ikke ignorere REST. For enkle integrasjoner, mobilapper som bare trenger en liste med innlegg, intern automatisering, webhooks og AI-agenter som bruker Abilities API, er det innebygde REST API-et fremdeles den raskeste veien til målet, uten noen utvidelse å vedlikeholde. Mange nettsteder i produksjon kjører begge: GraphQL for den offentlige frontenden, REST for integrasjoner.
Les mer om migrering av nettsteder til Astro og Next.js hos WPPoland.
Henter du fremdeles hele innleggsobjektet bare for å vise en tittel? Legg til _fields i dag, og planlegg overgangen til GraphQL når frontenden vokser ut av det.







