Le API REST sono API REST-in-Peace. Lunga vita a GraphQL.

Aggiornamento: questo articolo fa ora parte della mia "Introduzione completa a GraphQL".
Leggi la versione aggiornata di questo contenuto e altro su GraphQL su jscomplete.com/why-graphql.

Dopo anni di lavoro con le API REST, quando ho appreso per la prima volta di GraphQL e dei problemi che sta tentando di risolvere, non ho potuto resistere a twittare il titolo esatto di questo articolo.

Certo, allora, era solo un mio tentativo di essere divertente, ma oggi credo che la previsione divertente stia effettivamente accadendo.

Per favore, non interpretare questo male. Non ho intenzione di accusare GraphQL di "uccidere" REST o qualcosa del genere. Probabilmente REST non morirà mai, proprio come XML non ha mai fatto. Penso semplicemente che GraphQL farà per ripristinare ciò che JSON ha fatto a XML.

Questo articolo non è in realtà al 100% a favore di GraphQL. C'è una sezione molto importante sul costo della flessibilità di GraphQL. Con grande flessibilità arriva un grande costo.

Sono un grande fan di "Inizia sempre con PERCHÉ", quindi facciamolo.

In sintesi: Perché GraphQL?

I 3 problemi più importanti che GraphQL risolve magnificamente sono:

  • La necessità di eseguire più round trip per recuperare i dati richiesti da una vista: con GraphQL, è sempre possibile recuperare tutti i dati iniziali richiesti da una vista con un solo round trip per il server. Per fare lo stesso con un'API REST, dobbiamo introdurre parametri non strutturati e condizioni difficili da gestire e ridimensionare.
  • Dipendenza dei client dai server: con GraphQL, il client parla un linguaggio di richiesta che: 1) elimina la necessità che il server codifichi la forma o la dimensione dei dati e 2) disaccoppia i client dai server. Ciò significa che possiamo mantenere e migliorare i clienti separatamente dai server.
  • La brutta esperienza degli sviluppatori front-end: con GraphQL, gli sviluppatori esprimono i requisiti dei dati delle loro interfacce utente usando un linguaggio dichiarativo. Esprimono ciò di cui hanno bisogno, non come renderlo disponibile. Esiste una stretta relazione tra i dati necessari all'interfaccia utente e il modo in cui uno sviluppatore può esprimere una descrizione di tali dati in GraphQL.

Questo articolo spiegherà in dettaglio come GraphQL risolve tutti questi problemi.

Prima di iniziare, per quelli di voi che non hanno ancora familiarizzato con GraphQL, iniziamo con definizioni semplici.

Che cos'è GraphQL?

GraphQL è un linguaggio. Se insegniamo GraphQL a un'applicazione software, tale applicazione sarà in grado di comunicare in modo dichiarativo qualsiasi requisito di dati a un servizio dati di back-end che parla anche GraphQL.

Proprio come un bambino può imparare rapidamente una nuova lingua - mentre un adulto avrà più difficoltà a raccoglierla - avviare una nuova applicazione da zero utilizzando GraphQL sarà molto più semplice che introdurre GraphQL in un'applicazione matura.

Per insegnare a un servizio dati a parlare GraphQL, dobbiamo implementare un livello di runtime ed esporlo ai client che desiderano comunicare con il servizio. Pensa a questo livello sul lato server semplicemente come un traduttore del linguaggio GraphQL o un agente che parla GraphQL che rappresenta il servizio dati. GraphQL non è un motore di archiviazione, quindi non può essere una soluzione autonoma. Questo è il motivo per cui non possiamo avere un server che parla solo GraphQL e dobbiamo invece implementare un runtime di traduzione.

Questo livello, che può essere scritto in qualsiasi lingua, definisce uno schema generico basato su grafici per pubblicare le funzionalità del servizio dati che rappresenta. Le applicazioni client che parlano GraphQL possono interrogare quello schema all'interno delle sue capacità. Questo approccio disaccoppia i client dai server e consente a entrambi di evolversi e ridimensionarsi in modo indipendente.

Una richiesta GraphQL può essere una query (operazione di lettura) o una mutazione (operazione di scrittura). In entrambi i casi, la richiesta è una stringa semplice che un servizio GraphQL può interpretare, eseguire e risolvere con i dati in un formato specificato. Il formato di risposta popolare che viene solitamente utilizzato per applicazioni mobili e Web è JSON.

Che cos'è GraphQL? (La versione di Explain-it-like-I'm-5)

GraphQL è tutto sulla comunicazione dei dati. Hai un client e un server ed entrambi devono parlare tra loro. Il client deve comunicare al server di quali dati ha bisogno e il server deve soddisfare i requisiti di questo client con i dati effettivi. GraphQL entra nel mezzo di questa comunicazione.

Screenshot catturato dal mio corso Pluralsight - Creazione di API scalabili con GraphQL

Perché il client non può semplicemente comunicare direttamente con il server, chiedi? Certamente.

Esistono alcuni motivi per considerare un livello GraphQL tra client e server. Uno di questi motivi, e forse il più popolare, è l'efficienza. Il client di solito deve chiedere al server informazioni su più risorse e il server di solito capisce come rispondere con una singola risorsa. Quindi il client finisce per fare più round-trip verso il server per raccogliere tutti i dati di cui ha bisogno.

Con GraphQL, possiamo sostanzialmente spostare questa complessità multi-richiesta sul lato server e farci gestire il livello GraphQL. Il client pone al layer GraphQL una sola domanda e ottiene una singola risposta che ha esattamente ciò di cui il cliente ha bisogno.

Ci sono molti più vantaggi nell'utilizzo di un livello GraphQL. Ad esempio, un altro grande vantaggio è la comunicazione con più servizi. Quando si hanno più client che richiedono dati da più servizi, un livello GraphQL nel mezzo può semplificare e standardizzare questa comunicazione. Sebbene questo non sia realmente un punto contro le API REST - poiché è facile ottenere lo stesso risultato lì - un runtime GraphQL offre un modo strutturato e standardizzato di farlo.

Screenshot catturato dal mio corso Pluralsight - Creazione di API scalabili con GraphQL

Invece di un client che accede direttamente ai due diversi servizi dati (nella diapositiva sopra), possiamo far comunicare quel client con il livello GraphQL. Quindi il livello GraphQL farà la comunicazione con i due diversi servizi dati. Questo è il modo in cui GraphQL isola prima i client dalla necessità di comunicare in più lingue e traduce anche una singola richiesta in più richieste in più servizi utilizzando lingue diverse.

Immagina di avere tre persone che parlano tre lingue diverse e hanno diversi tipi di conoscenza. Quindi immagina di avere una domanda a cui è possibile rispondere solo combinando la conoscenza di tutte e tre le persone insieme. Se hai un traduttore che parla tutte e tre le lingue, il compito di mettere insieme una risposta alla tua domanda diventa facile. Questo è esattamente ciò che fa un runtime GraphQL.

I computer non sono abbastanza intelligenti da rispondere a qualsiasi domanda (almeno non ancora), quindi devono seguire un algoritmo da qualche parte. Questo è il motivo per cui è necessario definire uno schema sul runtime GraphQL e tale schema viene utilizzato dai client.

Lo schema è fondamentalmente un documento di funzionalità che ha un elenco di tutte le domande che il client può porre al livello GraphQL. C'è una certa flessibilità nell'uso dello schema perché stiamo parlando di un grafico di nodi qui. Lo schema rappresenta principalmente i limiti di ciò che può essere risposto dal livello GraphQL.

Ancora non chiaro? Chiamiamo GraphQL come è realmente e semplicemente: un sostituto delle API REST. Quindi lasciami rispondere alla domanda che molto probabilmente stai ponendo ora.

Cosa c'è di sbagliato con le API REST?

Il problema più grande con le API REST è la natura di più endpoint. Ciò richiede che i clienti facciano più viaggi di andata e ritorno per ottenere i loro dati.

Le API REST sono in genere una raccolta di endpoint, in cui ciascun endpoint rappresenta una risorsa. Pertanto, quando un cliente necessita di dati provenienti da più risorse, deve eseguire più round trip verso un'API REST per mettere insieme i dati di cui ha bisogno.

In un'API REST non esiste una lingua di richiesta client. I client non hanno il controllo sui dati che il server restituirà. Non esiste una lingua attraverso la quale possano farlo. Più precisamente, la lingua disponibile per i clienti è molto limitata.

Ad esempio, gli endpoint dell'API REST READ sono:

  • GET / ResourceName: per ottenere un elenco di tutti i record da quella risorsa, oppure
  • GET / ResourceName / ResourceID - per ottenere il singolo record identificato da quell'ID.

Un cliente non può, ad esempio, specificare quali campi selezionare per un record in quella risorsa. Tali informazioni si trovano nel servizio API REST stesso e il servizio API REST restituirà sempre tutti i campi indipendentemente da quelli effettivamente necessari al client. Il termine di GraphQL per questo problema è il recupero eccessivo di informazioni non necessarie. È uno spreco di risorse di rete e di memoria sia per il client che per il server.

Un altro grosso problema con le API REST è il controllo delle versioni. Se è necessario supportare più versioni, ciò significa in genere nuovi endpoint. Ciò comporta ulteriori problemi durante l'utilizzo e la manutenzione di tali endpoint e potrebbe essere la causa della duplicazione del codice sul server.

I problemi relativi alle API REST sopra menzionati sono specifici per ciò che GraphQL sta cercando di risolvere. Non sono certamente tutti i problemi delle API REST e non voglio entrare in ciò che un'API REST è e non lo è. Sto parlando principalmente delle famose API endpoint HTTP basate su risorse. Ognuna di queste API alla fine si trasforma in un mix che ha endpoint REST regolari + endpoint ad-hoc personalizzati realizzati per motivi di prestazioni. È qui che GraphQL offre un'alternativa molto migliore.

Come fa GraphQL a fare la sua magia?

Ci sono molti concetti e decisioni di progettazione dietro GraphQL, ma probabilmente i più importanti sono:

  • Uno schema GraphQL è uno schema fortemente tipizzato. Per creare uno schema GraphQL, definiamo i campi che hanno tipi. Questi tipi possono essere primitivi o personalizzati e tutto il resto nello schema richiede un tipo. Questo sistema di tipo avanzato consente funzionalità avanzate come avere un'API introspettiva e essere in grado di creare potenti strumenti per client e server.
  • GraphQL parla ai dati come un grafico e i dati sono naturalmente un grafico. Se è necessario rappresentare qualsiasi dato, la struttura corretta è un grafico. Il runtime GraphQL ci consente di rappresentare i nostri dati con un'API grafica che corrisponde alla forma naturale del grafico di tali dati.
  • GraphQL ha una natura dichiarativa per esprimere i requisiti dei dati. GraphQL offre ai clienti un linguaggio dichiarativo per esprimere le loro esigenze in termini di dati. Questa natura dichiarativa crea un modello mentale attorno all'uso del linguaggio GraphQL che è vicino al modo in cui pensiamo ai requisiti dei dati in inglese e rende il lavoro con un'API GraphQL molto più semplice delle alternative.

L'ultimo concetto è il motivo per cui personalmente credo che GraphQL sia un punto di svolta.

Questi sono tutti concetti di alto livello. Entriamo in qualche dettaglio in più.

Per risolvere il problema di andata e ritorno multipla, GraphQL rende il server di risposta solo un singolo endpoint. Fondamentalmente, GraphQL porta l'idea dell'endpoint personalizzato all'estremo e trasforma l'intero server in un unico endpoint personalizzato in grado di rispondere a tutte le domande sui dati.

L'altro grande concetto associato a questo singolo endpoint è il linguaggio di richiesta rich client necessario per lavorare con quel singolo endpoint personalizzato. Senza una lingua di richiesta client, un singolo endpoint è inutile. Ha bisogno di una lingua per elaborare una richiesta personalizzata e rispondere con i dati per quella richiesta personalizzata.

Avere una lingua di richiesta client significa che i client avranno il controllo. Possono chiedere esattamente ciò di cui hanno bisogno e il server risponderà esattamente con ciò che stanno chiedendo. Questo risolve il problema di recupero eccessivo.

Quando si tratta di versioning, GraphQL ha un'interessante opinione su questo. Il controllo delle versioni può essere evitato tutti insieme. Fondamentalmente, possiamo semplicemente aggiungere nuovi campi senza rimuovere quelli vecchi, perché abbiamo un grafico e possiamo far crescere il grafico in modo flessibile aggiungendo più nodi. Quindi possiamo lasciare percorsi nel grafico per le vecchie API e introdurne di nuove senza etichettarle come nuove versioni. L'API cresce.

Ciò è particolarmente importante per i client mobili perché non possiamo controllare la versione dell'API che stanno utilizzando. Una volta installata, un'app mobile potrebbe continuare a utilizzare la stessa vecchia versione dell'API per anni. Sul Web, è facile controllare la versione dell'API perché è sufficiente inviare un nuovo codice. Per le app mobili, è molto più difficile da fare.

Non sei ancora del tutto convinto? Che ne dici di fare un confronto one-to-one tra GraphQL e REST con un esempio reale?

API RESTful vs API GraphQL - Esempio

Immaginiamo di essere gli sviluppatori responsabili della costruzione di una nuova interfaccia utente brillante per rappresentare i film e i personaggi di Star Wars.

La prima interfaccia utente che ci è stata assegnata è semplice: una vista per mostrare informazioni su una singola persona di Star Wars. Ad esempio, Darth Vader e tutti i film in cui appare questa persona. Questa vista dovrebbe mostrare il nome della persona, l'anno di nascita, il nome del pianeta e i titoli di tutti i film in cui sono apparsi.

Per quanto possa sembrare semplice, qui abbiamo a che fare con 3 diverse risorse: Person, Planet e Film. La relazione tra queste risorse è semplice e chiunque può indovinare la forma dei dati qui. Un oggetto persona appartiene a un oggetto pianeta e avrà uno o più oggetti film.

I dati JSON per questa interfaccia utente potrebbero essere simili a:

{
  "dati": {
    "persona": {
      "name": "Darth Vader",
      "birthYear": "41.9BBY",
      "pianeta": {
        "name": "Tatooine"
      },
      "film": [
        {"title": "A New Hope"},
        {"title": "The Empire Strikes Back"},
        {"title": "Return of the Jedi"},
        {"title": "Revenge of the Sith"}
      ]
    }
  }
}

Supponendo che un servizio dati ci abbia fornito questa esatta struttura per i dati, ecco un modo possibile per rappresentare la sua vista con React.js:

// Il componente contenitore:
 
// Il componente PersonProfile:
Nome: {person.name}
Anno di nascita: {person.birthYear}
Planet: {person.planet.name}
Film: {person.films.map (film => film.title)}

Questo è un semplice esempio e mentre la nostra esperienza con Star Wars potrebbe averci aiutato un po 'qui, la relazione tra l'interfaccia utente e i dati è molto chiara. L'interfaccia utente ha utilizzato tutte le "chiavi" dall'oggetto dati JSON che immaginavamo.

Vediamo ora come possiamo richiedere questi dati utilizzando un'API RESTful.

Abbiamo bisogno delle informazioni di una singola persona e supponendo di conoscere l'ID di quella persona, un'API RESTful dovrebbe esporre tali informazioni come:

OTTIENI - / people / {id}

Questa richiesta ci fornirà il nome, la nascita dell'anno e altre informazioni sulla persona. Una buona API RESTful ci fornirà anche l'ID del pianeta di questa persona e una serie di ID per tutti i film in cui questa persona è apparsa.

La risposta JSON per questa richiesta potrebbe essere qualcosa del tipo:

{
  "name": "Darth Vader",
  "birthYear": "41.9BBY",
  "planetId": 1
  "filmIds": [1, 2, 3, 6],
  *** altre informazioni non necessarie ***
}

Quindi per leggere il nome del pianeta, chiediamo:

OTTIENI - / pianeti / 1

E per leggere i titoli dei film, chiediamo:

OTTIENI - / films / 1
OTTIENI - / films / 2
OTTIENI - / films / 3
OTTIENI - / films / 6

Una volta ottenute tutte e 6 le risposte dal server, possiamo combinarle per soddisfare i dati richiesti dalla nostra vista.

Oltre al fatto che abbiamo dovuto fare 6 viaggi di andata e ritorno per soddisfare una semplice necessità di dati per una semplice interfaccia utente, il nostro approccio qui era imperativo. Abbiamo fornito istruzioni su come recuperare i dati e su come elaborarli per renderli pronti per la visualizzazione.

Puoi provarlo tu stesso se vuoi vedere cosa intendo. I dati di Star Wars hanno un'API RESTful attualmente ospitata su http://swapi.co/. Vai avanti e prova a costruire lì il nostro oggetto persona dati. Le chiavi potrebbero essere leggermente diverse, ma gli endpoint API saranno gli stessi. Dovrai fare esattamente 6 chiamate API. Inoltre, dovrai recuperare eccessivamente le informazioni non necessarie alla vista.

Naturalmente, questa è solo un'implementazione di un'API RESTful per questi dati. Potrebbero esserci implementazioni migliori che renderanno questa visione più facile da implementare. Ad esempio, se il server API implementasse risorse nidificate e comprendesse la relazione tra una persona e un film, potremmo leggere i dati dei film con:

OTTIENI - / people / {id} / films

Tuttavia, molto probabilmente un server API RESTful puro non lo implementerebbe e dovremmo chiedere ai nostri ingegneri di backend di creare questo endpoint personalizzato per noi. Questa è la realtà del ridimensionamento di un'API RESTful: aggiungiamo solo endpoint personalizzati per soddisfare in modo efficiente le crescenti esigenze dei clienti. Gestire endpoint personalizzati come questi è difficile.

Vediamo ora l'approccio GraphQL. GraphQL sul server abbraccia l'idea di endpoint personalizzati e la porta all'estremo. Il server sarà solo un singolo endpoint e il canale non ha importanza. Se lo stiamo facendo su HTTP, neanche il metodo HTTP non importerebbe. Supponiamo di avere un singolo endpoint GraphQL esposto su HTTP a / graphql.

Poiché desideriamo richiedere i dati di cui abbiamo bisogno in un solo round trip, avremo bisogno di un modo per esprimere le nostre esigenze di dati complete per il server. Lo facciamo con una query GraphQL:

OTTIENI o POST - / graphql? Query = {...}

Una query GraphQL è solo una stringa, ma dovrà includere tutte le parti dei dati di cui abbiamo bisogno. È qui che entra in gioco il potere dichiarativo.

In inglese, ecco come dichiariamo il nostro requisito di dati: abbiamo bisogno del nome di una persona, dell'anno di nascita, del nome del pianeta e dei titoli di tutti i loro film. In GraphQL, questo si traduce in:

{
  persona (ID: ...) {
    nome,
    anno di nascita,
    pianeta {
      nome
    },
    film {
      titolo
    }
  }
}

Leggi i requisiti espressi in inglese ancora una volta e confrontali con la query GraphQL. È il più vicino possibile. Ora, confronta questa query GraphQL con i dati JSON originali con cui abbiamo iniziato. La query GraphQL è la struttura esatta dei dati JSON, eccetto senza tutte le parti di "valori". Se pensiamo a questo in termini di una relazione domanda-risposta, la domanda è la dichiarazione di risposta senza la parte di risposta.

Se la dichiarazione di risposta è:

Il pianeta più vicino al Sole è Mercurio.

Una buona rappresentazione della domanda è la stessa affermazione senza la parte di risposta:

(Qual è) il pianeta più vicino al Sole?

La stessa relazione si applica a una query GraphQL. Prendi una risposta JSON, rimuovi tutte le parti di "risposta" (che sono i valori) e finisci con una query GraphQL molto adatta a rappresentare una domanda su quella risposta JSON.

Ora, confronta la query GraphQL con l'interfaccia utente React dichiarativa che abbiamo definito per i dati. Tutto nella query GraphQL viene utilizzato nell'interfaccia utente e tutto ciò che viene utilizzato nell'interfaccia utente viene visualizzato nella query GraphQL.

Questo è il grande modello mentale di GraphQL. L'interfaccia utente conosce i dati esatti di cui ha bisogno ed estrarre tale requisito è abbastanza semplice. Elaborare una query GraphQL è semplicemente il compito di estrarre ciò che viene utilizzato come variabili direttamente dall'interfaccia utente.

Se invertissimo questo modello, manterrebbe comunque il potere. Se disponiamo di una query GraphQL, sappiamo esattamente come utilizzare la sua risposta nell'interfaccia utente perché la query avrà la stessa "struttura" della risposta. Non abbiamo bisogno di ispezionare la risposta per sapere come usarla e non abbiamo bisogno di alcuna documentazione sull'API. È tutto integrato.

I dati di Star Wars hanno un'API GraphQL ospitata su https://github.com/graphql/swapi-graphql. Vai avanti e prova a costruire lì il nostro oggetto persona dati. Ci sono alcune differenze minori che spiegheremo più avanti, ma ecco la query ufficiale che puoi utilizzare contro questa API per leggere il nostro requisito di dati per la vista (con Darth Vader come esempio):

{
  persona (personID: 4) {
    nome,
    anno di nascita,
    homeworld {
      nome
    },
    filmConnection {
      film {
        titolo
      }
    }
  }
}

Questa richiesta ci fornisce una struttura di risposta molto simile a quella utilizzata dalla nostra vista e, ricorda, stiamo ottenendo tutti questi dati in un unico round-trip.

Il costo della flessibilità di GraphQL

Le soluzioni perfette sono le fiabe. Con la flessibilità di GraphQL, si aprono le porte ad alcuni chiari problemi e preoccupazioni.

Un'importante minaccia che GraphQL semplifica sono gli attacchi di esaurimento delle risorse (attacchi AKA Denial of Service). Un server GraphQL può essere attaccato con query troppo complesse che consumeranno tutte le risorse del server. È molto semplice cercare relazioni nidificate in profondità (utente -> amici -> amici ...) o utilizzare gli alias di campo per richiedere lo stesso campo più volte. Gli attacchi all'esaurimento delle risorse non sono specifici di GraphQL, ma quando si lavora con GraphQL dobbiamo prestare particolare attenzione a questi.

Ci sono alcune mitigazioni che possiamo fare qui. Possiamo eseguire in anticipo l'analisi dei costi sulla query e applicare alcuni tipi di limiti sulla quantità di dati che è possibile consumare. Possiamo anche implementare un timeout per eliminare le richieste che richiedono troppo tempo per essere risolte. Inoltre, poiché GraphQL è solo un livello di risoluzione, in GraphQL possiamo gestire l'applicazione dei limiti di velocità a un livello inferiore.

Se l'endpoint dell'API GraphQL che stiamo cercando di proteggere non è pubblico ed è destinato al consumo interno dei nostri clienti (web o mobile), possiamo utilizzare un approccio di whitelist e pre-approvare le query che il server può eseguire. I clienti possono semplicemente chiedere ai server di eseguire query pre-approvate utilizzando un identificatore univoco della query. Facebook sembra utilizzare questo approccio.

Autenticazione e autorizzazione sono altre preoccupazioni che dobbiamo considerare quando si lavora con GraphQL. Li gestiamo prima, dopo o durante un processo di risoluzione di GraphQL?

Per rispondere a questa domanda, pensa a GraphQL come un DSL (linguaggio specifico del dominio) in aggiunta alla tua logica di recupero dei dati di back-end. È solo uno strato che potremmo mettere tra i clienti e il nostro servizio dati effettivo (o più servizi).

Pensa all'autenticazione e all'autorizzazione come a un altro livello. GraphQL non aiuterà con l'implementazione effettiva della logica di autenticazione o autorizzazione. Non è pensato per questo. Ma se vogliamo mettere questi livelli dietro GraphQL, possiamo usare GraphQL per comunicare i token di accesso tra i client e la logica di applicazione. Questo è molto simile al modo in cui eseguiamo l'autenticazione e l'autorizzazione con le API RESTful.

Un'altra attività che GraphQL rende un po 'più impegnativa è la memorizzazione nella cache dei dati del client. Le API RESTful sono più facili da memorizzare nella cache a causa della loro natura del dizionario. Questa posizione fornisce tali dati. Possiamo usare la posizione stessa come chiave della cache.

Con GraphQL, possiamo adottare un approccio di base simile e utilizzare il testo della query come chiave per memorizzare nella cache la sua risposta. Ma questo approccio è limitato, non molto efficiente e può causare problemi di coerenza dei dati. I risultati di più query GraphQL possono facilmente sovrapporsi e questo approccio di cache di base non spiegherebbe la sovrapposizione.

C'è una brillante soluzione a questo problema però. Una query del grafico indica una cache del grafico. Se normalizziamo una risposta di query GraphQL in una raccolta semplice di record, dando a ciascun record un ID univoco globale, possiamo memorizzare tali record nella cache invece di memorizzare nella cache le risposte complete.

Questo non è un processo semplice però. Ci saranno record che fanno riferimento ad altri record e gestiremo un grafico ciclico lì. Il popolamento e la lettura della cache dovranno essere eseguiti su query. Dobbiamo codificare un livello per gestire la logica della cache. Ma questo metodo sarà nel complesso molto più efficiente della cache basata sulla risposta. Relay.js è un framework che adotta questa strategia di memorizzazione nella cache e la gestisce automaticamente internamente.

Forse il problema più importante di cui dovremmo preoccuparci con GraphQL è il problema che viene comunemente chiamato query SQL N + 1. I campi di query GraphQL sono progettati per essere funzioni autonome e la risoluzione di tali campi con dati da un database potrebbe comportare una nuova richiesta di database per campo risolto.

Per una semplice logica dell'endpoint API RESTful, è facile analizzare, rilevare e risolvere i problemi N + 1 migliorando le query SQL costruite. Per GraphQL campi risolti dinamicamente, non è così semplice. Fortunatamente Facebook sta aprendo la strada a una possibile soluzione a questo problema: DataLoader.

Come suggerisce il nome, DataLoader è un'utilità che è possibile utilizzare per leggere i dati dai database e renderli disponibili per le funzioni del resolver GraphQL. Possiamo usare DataLoader invece di leggere i dati direttamente dai database con query SQL e DataLoader fungerà da nostro agente per ridurre le query SQL effettive che inviamo al database.

DataLoader utilizza una combinazione di batch e memorizzazione nella cache per ottenere ciò. Se la stessa richiesta client ha comportato la necessità di chiedere al database più cose, DataLoader può essere utilizzato per consolidare queste domande e caricare in batch le loro risposte dal database. DataLoader memorizzerà anche le risposte nella cache e le renderà disponibili per le domande successive sulle stesse risorse.

Grazie per aver letto.

Imparare React o Node? Dai un'occhiata ai miei libri:

  • Scopri React.js costruendo giochi
  • Node.js Oltre le basi