GraphQL vs REST: gli stessi dati recuperati nei due modi | We.Inc
Confronta GraphQL e REST con gli stessi dati recuperati nei due modi: numero di richieste, over-fetching, caching, come tornano gli errori e una tabella per scegliere.
REST espone molti URL, uno per risorsa, e il server decide cosa contiene ogni risposta. GraphQL espone un unico endpoint, di solito /graphql, a cui il client invia una query che indica esattamente i campi che vuole. REST ottiene gratis il caching HTTP per URL; GraphQL risparmia round trip ed elimina i campi inutilizzati, al prezzo di più lavoro sul server.
In sintesi
Tema
REST
GraphQL
Endpoint
Un URL per risorsa
Un solo endpoint, spesso /graphql
Chi sceglie i campi
Il server
Il client, nella query
Dati correlati
Spesso più richieste
Annidati in una sola query
Caching HTTP
Integrato per le GET tramite URL
Richiede query GET, persisted query o una cache lato client
Errori
Soprattutto codici di stato HTTP
Un array errors, spesso accanto a dati parziali
Schema
Opzionale (OpenAPI)
Obbligatorio e tipizzato
Il confronto qui sotto recupera la stessa schermata di dati nei due modi. Scegli uno scenario per vedere le chiamate REST che un client farebbe accanto all'unica query GraphQL che le sostituisce, e cosa ogni risposta omette o aggiunge.
Scegli uno scenario, per esempio una pagina profilo con i post recenti.
Leggi le richieste REST a sinistra e la query GraphQL a destra.
Confronta il numero di richieste mostrato sotto i pannelli.
Leggi la nota per vedere dove ciascuno stile invia più dati di quelli che servono alla schermata.
Non passare a GraphQL un'API REST che funziona solo per moda. Il vantaggio emerge quando molte schermate diverse hanno bisogno di porzioni diverse di dati correlati.
Esponi un campo id stabile su ogni tipo GraphQL così le librerie client possono normalizzare la cache in base a quello.
Controlla l'array errors in ogni risposta GraphQL, anche quando lo stato è 200 e i dati sono presenti.
Imposta limiti di profondità e di costo su un endpoint GraphQL pubblico, perché una sola query annidata può richiedere moltissimo lavoro.
Domande frequenti
GraphQL è più veloce di REST?
Non di per sé. Può ridurre i round trip e la dimensione del payload per le schermate che richiedono dati correlati, ma ogni query può costare di più al server per essere risolta. Un endpoint REST ben progettato per una singola schermata può essere altrettanto rapido.
Perché un errore GraphQL torna con stato 200?
Un campo può fallire mentre altri riescono, quindi il server restituisce i dati che ha più un array errors. Le linee guida GraphQL over HTTP usano 2xx per il successo parziale; i server che rispondono con application/graphql-response+json usano 400 quando una richiesta non supera la validazione.
Le risposte GraphQL si possono mettere in cache su una CDN?
Sì, se le query vengono inviate con GET, cosa che i server possono consentire solo per le query. Le query lunghe possono superare i limiti degli URL, quindi i team usano le persisted query che inviano un breve hash invece dell'intero documento.
Posso usarli entrambi in un unico prodotto?
Molti team lo fanno. Upload di file, webhook e semplici risorse pubbliche restano spesso route REST, mentre le schermate dell'app leggono tramite uno strato GraphQL che può chiamare sotto quegli stessi servizi.
GraphQL ha bisogno di un database proprio?
No. Un server GraphQL è uno strato di resolver, piccole funzioni che recuperano ogni campo da dove si trovano i dati: un database, un servizio REST o un file. Lo schema descrive forme, non lo storage.
Over-fetching e under-fetching
Un endpoint REST restituisce una forma fissa. Una schermata elenco che mostra solo i nomi scarica comunque ogni campo di ogni utente: questo è over-fetching. Una schermata di dettaglio che richiede un utente più i suoi post più il numero di commenti di ogni post può richiedere diverse chiamate: questo è under-fetching.
GraphQL sposta quella scelta sul client. La query elenca i campi, il server restituisce quella forma e nient'altro. Il compromesso è che il server deve gestire qualsiasi combinazione di campi un client possa chiedere.
Il caching funziona in modo diverso
Con REST, un URL è una chiave di cache. Browser e CDN possono salvare una risposta GET e riutilizzarla, perché GET e HEAD sono i metodi cacheable. La maggior parte del traffico GraphQL è una POST verso un unico URL, che quelle cache non salvano.
I client GraphQL compensano nell'app: dividono le risposte in oggetti e li salvano per id, così due query che toccano lo stesso utente condividono un unico record in cache. graphql.org raccomanda un campo id univoco a livello globale proprio per questo motivo.
Errori e codici di stato
REST si appoggia alla riga di stato: 404 per un record mancante, 401 quando non hai effettuato l'accesso, 422 per un input non valido. I client possono decidere in base al solo codice.
Una risposta GraphQL ha una chiave data, una chiave errors, o entrambe. Un problema di sintassi o di validazione dà errors e nessun data. Un errore dentro un singolo campo dà dati parziali in cui quel campo è null, e una voce di errore il cui path punta a quel campo.
Quale scegliere
Tabella decisionale
La tua situazione
Tende verso
API pubblica che terze parti chiamano con curl
REST
Molte schermate, ognuna con dati correlati diversi
GraphQL
Caching intenso su CDN del traffico in lettura
REST, oppure GraphQL con persisted query in GET
Client mobili su reti lente
GraphQL, meno round trip
Semplice CRUD su poche tabelle
REST
Diversi servizi backend dietro un unico punto di ingresso
GraphQL come strato gateway
Cosa passa sulla rete
Una richiesta GraphQL con fetch
Ogni operazione è una POST di JSON con le chiavi query e variables verso l'unico endpoint. L'header Accept chiede il tipo di risposta GraphQL più recente, con il JSON semplice come fallback.
Una risposta GraphQL parziale
Un campo è fallito, quindi è null e la voce in errors lo indica con path. Il resto dei dati è comunque arrivato.
Profilo con post
REST richiede una seconda chiamata per i post, ed entrambe le risposte includono ogni campo previsto dal server. La query GraphQL restituisce solo il nome, l'avatar e tre titoli di post.
Solo i nomi
Per un semplice elenco la chiamata REST è comunque una sola richiesta, ma invia i record utente completi. GraphQL invia solo i due campi richiesti.
Post con commenti e autori
Senza un endpoint personalizzato, REST percorre l'albero un livello per richiesta, e recuperare l'autore di ogni commento può significare una chiamata in più per commento. GraphQL annida l'intero albero in una sola query.
Creare un post
Le scritture si somigliano: una richiesta ciascuna. REST usa il metodo POST su un URL di collezione; GraphQL invia una mutation, sempre come HTTP POST, e sceglie quali campi del nuovo post restituire.