Un'introduzione completa ad Apollo, il toolkit GraphQL

Ti interessa imparare JavaScript? Ottieni il mio ebook gratuito su jshandbook.com

Introduzione ad Apollo

Negli ultimi anni, GraphQL è diventato estremamente popolare come approccio alternativo alla costruzione di un'API su REST.

GraphQL è un ottimo modo per consentire al client di decidere quali dati vogliono trasmettere sulla rete, piuttosto che far sì che il server invii un set fisso di dati.

Inoltre, ti consente di specificare le risorse nidificate, riducendo talvolta le operazioni necessarie per gestire le API REST.

Apollo è un team e una comunità che si basa su GraphQL e offre diversi strumenti che ti aiutano a costruire i tuoi progetti.

Logo Apollo per gentile concessione di apollographql.com

Gli strumenti forniti da Apollo sono principalmente tre: Client, Server, Engine.

Apollo Client ti aiuta a consumare un'API GraphQL, con il supporto per le tecnologie web frontend più popolari come React, Vue, Angular, Ember e Meteor. Supporta anche lo sviluppo nativo su iOS e Android.

Apollo Server è la parte server di GraphQL, che si interfaccia con il back-end e invia le risposte alle richieste del client.

Apollo Engine è un'infrastruttura ospitata (SaaS) che funge da intermediario tra il client e il server, fornendo cache, report delle prestazioni, misurazione del carico, tracciamento degli errori, statistiche sull'utilizzo dei campi dello schema, statistiche storiche e molte altre chicche. Attualmente è gratuito fino a 1 milione di richieste al mese ed è l'unica parte di Apollo che non è open source e gratuita. Fornisce finanziamenti per la parte open source del progetto.

Vale la pena notare che questi tre strumenti non sono collegati tra loro in alcun modo e puoi utilizzare solo Apollo Client per interfacciarsi con un'API di terza parte o servire un'API utilizzando Apollo Server senza avere un client, ad esempio.

Alcuni vantaggi dell'utilizzo di Apollo

È tutto compatibile con le specifiche standard GraphQL, quindi non esiste alcuna tecnologia proprietaria o incompatibile in Apollo.

Ma è molto conveniente avere tutti quegli strumenti insieme sotto un unico tetto come una suite completa per tutte le esigenze relative a GraphQL.

Apollo si impegna per essere facile da usare e facile da contribuire.

Apollo Client e Apollo Server sono tutti progetti della community, realizzati dalla community, per la community. Apollo è supportato dal Meteor Development Group (la società dietro Meteor), un framework JavaScript molto popolare.

Apollo si concentra sul mantenere le cose semplici. Questa è una chiave per il successo di una tecnologia che vuole diventare popolare. Gran parte della tecnologia, delle strutture o delle biblioteche disponibili potrebbe essere eccessiva per il 99% delle piccole o medie imprese, ed è davvero adatta per le grandi aziende con esigenze molto complesse.

Cliente Apollo

Apollo Client è il principale client JavaScript per GraphQL. Dal momento che è guidato dalla comunità, è progettato per consentire di creare componenti dell'interfaccia utente che si interfacciano con i dati GraphQL, sia nella visualizzazione di tali dati sia nell'esecuzione di mutazioni quando si verificano determinate azioni.

Non è necessario modificare tutto nell'applicazione per utilizzare Apollo Client. Puoi iniziare con solo un piccolo livello e una richiesta ed espandere da lì.

Soprattutto, Apollo Client è progettato per essere semplice, piccolo e flessibile da zero.

In questo post illustrerò in dettaglio il processo di utilizzo di Apollo Client all'interno di un'applicazione React.

Userò l'API GraphQL GitHub come server.

Avvia un'app React

Uso create-reazioni-app per configurare l'app React, che è molto conveniente e aggiunge solo le ossa nude di ciò di cui abbiamo bisogno:

myapp di npx create -eagire-app
npx è un comando disponibile nelle ultime versioni di npm. Aggiorna npm se non hai questo comando.

Avviare il server locale dell'app con

inizio del filato

Apri src / index.js:

import React da 'reagire'
importa ReactDOM da 'reazioni-dom'
import './index.css'
importa l'app da './App'
import registerServiceWorker da './registerServiceWorker'

ReactDOM.render (, document.getElementById ('root'))
registerServiceWorker ()

e rimuovi tutto questo contenuto.

Inizia con Apollo Boost

Apollo Boost è il modo più semplice per iniziare a utilizzare Apollo Client su un nuovo progetto. Installeremo questo oltre a reagire-apollo e graphql.

Nella console, esegui

filato aggiungere apollo-boost reagire-apollo graphql

o con npm:

npm installa apollo-boost reply-apollo graphql --save

Crea un oggetto ApolloClient

Si inizia importando ApolloClient da apollo-client in index.js:

importare {ApolloClient} da 'apollo-client'

const client = new ApolloClient ()

Per impostazione predefinita, Apollo Client utilizza l'endpoint / graphql sull'host corrente, quindi utilizziamo un Apollo Link per specificare i dettagli della connessione al server GraphQL impostando l'URI dell'endpoint GraphQL.

Link Apollo

Un Apollo Link è rappresentato da un oggetto HttpLink, che importiamo da apollo-link-http.

Apollo Link ci fornisce un modo per descrivere come vogliamo ottenere il risultato di un'operazione GraphQL e cosa vogliamo fare con la risposta.

In breve, si creano più istanze Apollo Link che agiscono tutte su una richiesta GraphQL una dopo l'altra, fornendo il risultato finale desiderato. Alcuni collegamenti possono darti la possibilità di ritentare una richiesta in caso di esito negativo, il batch e molto altro.

Aggiungeremo un Apollo Link alla nostra istanza di Apollo Client per utilizzare l'URI dell'endpoint GitHub GraphQL https://api.github.com/graphql

importare {ApolloClient} da 'apollo-client'
importare {HttpLink} da 'apollo-link-http'

const client = new ApolloClient ({
  link: nuovo HttpLink ({uri: 'https://api.github.com/graphql'})
})

caching

Non abbiamo ancora finito. Prima di avere un esempio funzionante, dobbiamo anche dire ad ApolloClient quale strategia di memorizzazione nella cache utilizzare: InMemoryCache è l'impostazione predefinita ed è una buona scelta con cui iniziare.

importare {ApolloClient} da 'apollo-client'
importare {HttpLink} da 'apollo-link-http'
importare {InMemoryCache} da 'apollo-cache-inmemory'

const client = new ApolloClient ({
  link: nuovo HttpLink ({uri: 'https://api.github.com/graphql'}),
  cache: new InMemoryCache ()
})

Usa ApolloProvider

Ora dobbiamo collegare il client Apollo al nostro albero dei componenti. Lo facciamo usando ApolloProvider, avvolgendo il nostro componente dell'applicazione nel file React principale:

import React da 'reagire'
importa ReactDOM da 'reazioni-dom'
importare {ApolloClient} da 'apollo-client'
importare {HttpLink} da 'apollo-link-http'
importare {InMemoryCache} da 'apollo-cache-inmemory'
importare {ApolloProvider} da 'reazioni-apollo'

importa l'app da './App'

const client = new ApolloClient ({
  link: nuovo HttpLink ({uri: 'https://api.github.com/graphql'}),
  cache: new InMemoryCache ()
})

ReactDOM.render (
  
    
  ,
  document.getElementById ( 'radice')
)

Questo è sufficiente per eseguire il rendering della schermata predefinita create -eagire-app, con il client Apollo inizializzato:

Il tag del modello gql

Ora siamo pronti a fare qualcosa con Apollo Client e recupereremo alcuni dati dall'API GitHub e li renderizzeremo.

Per fare ciò, dobbiamo importare il tag del modello gql:

importa gql da 'graphql-tag'

Qualsiasi query GraphQL verrà creata utilizzando questo tag modello, in questo modo:

const query = gql`
  query {
    ...
  }
`

Eseguire una richiesta GraphQL

gql è stato l'ultimo elemento di cui avevamo bisogno nel nostro set di strumenti.

Ora siamo pronti a fare qualcosa con Apollo Client e recupereremo alcuni dati dall'API GitHub e li renderizzeremo.

Ottieni un token di accesso per l'API

La prima cosa da fare è ottenere un token di accesso personale da GitHub.

GitHub semplifica fornendo un'interfaccia da cui selezionare qualsiasi autorizzazione di cui potreste aver bisogno:

Per il bene di questo tutorial di esempio, non hai bisogno di nessuna di queste autorizzazioni. Sono pensati per l'accesso ai dati degli utenti privati, ma eseguiremo semplicemente una query sui dati dei repository pubblici.

Il token che ottieni è un token Bearer OAuth 2.0.

Puoi facilmente testarlo eseguendo dalla riga di comando:

$ curl -H "Autorizzazione: portatore *** _ YOUR_TOKEN_HERE _ ***" -X POST -d "\
 {\
   \ "query \": \ "query {viewer {login}} \" \
 } \
"https://api.github.com/graphql

che dovrebbe darti il ​​risultato

{ "Dati": { "Viewer": { "login": "*** _ YOUR_LOGIN_NAME _ ***"}}}

o

{
  "message": "Credenziali errate",
  "documentazione_url": "https://developer.github.com/v4"
}

se qualcosa è andato storto.

Usa un Apollo Link per autenticarti

Quindi, dobbiamo inviare l'intestazione di autorizzazione insieme alla nostra richiesta GraphQL, proprio come abbiamo fatto nella richiesta di arricciatura sopra.

Possiamo farlo con Apollo Client creando un middleware Apollo Link. Inizia con l'installazione di apollo-link-context:

npm installa apollo-link-context

Questo pacchetto ci consente di aggiungere un meccanismo di autenticazione impostando il contesto delle nostre richieste.

Possiamo usarlo in questo codice facendo riferimento alla funzione setContext in questo modo:

const authLink = setContext ((_, {headers}) => {
  const token = '*** YOUR_TOKEN **'

  ritorno {
    intestazioni: {
      ... intestazioni,
      autorizzazione: `Bearer $ {token}`
    }
  }
})

e una volta che abbiamo questo nuovo Apollo Link, possiamo comporlo con l'HttpLink che già avevamo usando il metodo concat () su un link:

const link = authLink.concat (httpLink)

Ecco il codice completo per il file src / index.js con il codice che abbiamo in questo momento:

import React da 'reagire'
importa ReactDOM da 'reazioni-dom'
importare {ApolloClient} da 'apollo-client'
importare {HttpLink} da 'apollo-link-http'
importare {InMemoryCache} da 'apollo-cache-inmemory'
importare {ApolloProvider} da 'reazioni-apollo'
importare {setContext} da 'apollo-link-context'
importa gql da 'graphql-tag'

importa l'app da './App'

const httpLink = new HttpLink ({uri: 'https://api.github.com/graphql'})

const authLink = setContext ((_, {headers}) => {
  const token = '*** YOUR_TOKEN **'

  ritorno {
    intestazioni: {
      ... intestazioni,
      autorizzazione: `Bearer $ {token}`
    }
  }
})

const link = authLink.concat (httpLink)

const client = new ApolloClient ({
  link: link,
  cache: new InMemoryCache ()
})

ReactDOM.render (
  
    
  ,
  document.getElementById ( 'radice')
)
ATTENZIONE Ricorda che questo codice è un esempio a scopo educativo. Espone l'API GraphQL di GitHub affinché il mondo possa vederla nel tuo codice front-end. Il codice di produzione deve mantenere privato questo token.

Ora possiamo fare la prima richiesta GraphQL nella parte inferiore di questo file e questa query di esempio richiede i nomi e i proprietari dei 10 repository più popolari con oltre 50k stelle:

const POPULAR_REPOSITORIES_LIST = gql`
{
  ricerca (query: "stelle:> 50000", tipo: REPOSITORY, prima: 10) {
    repositoryCount
    bordi {
      nodo {
        ... sul repository {
          nome
          proprietario {
            accesso
          }
          stargazers {
            conteggio totale
          }
        }
      }
    }
  }
}
`

client.query ({query: POPULAR_REPOSITORIES_LIST}). quindi (console.log)

L'esecuzione corretta di questo codice restituisce il risultato della nostra query nella console del browser:

Rendering di un set di risultati della query GraphQL in un componente

Ciò che abbiamo visto finora è già bello. Ciò che è ancora più interessante è l'utilizzo del set di risultati GraphQL per il rendering dei componenti.

Lasciamo che Apollo Client abbia l'onere (o la gioia) o di recuperare i dati e gestire tutte le cose di basso livello. Questo ci consente di concentrarci sulla visualizzazione dei dati utilizzando il potenziatore del componente graphql offerto da reag-apollo:

import React da 'reagire'
import {graphql} da 'reazioni-apollo'
import {gql} da 'apollo-boost'

const POPULAR_REPOSITORIES_LIST = gql`
{
  ricerca (query: "stelle:> 50000", tipo: REPOSITORY, prima: 10) {
    repositoryCount
    bordi {
      nodo {
        ... sul repository {
          nome
          proprietario {
            accesso
          }
          stargazers {
            conteggio totale
          }
        }
      }
    }
  }
}
`

const App = graphql (POPULAR_REPOSITORIES_LIST) (props =>
  
        {props.data.loading? '': props.data.search.edges.map ((row, i) =>       
  •         {row.node.owner.login} / {row.node.name}: {''}                    {} Row.node.stargazers.totalCount                     )}    ) esporta l'app predefinita

Ecco il risultato della nostra query resa nel componente

Apollo Server

Un server GraphQL ha il compito di accettare le richieste in arrivo su un endpoint, interpretare la richiesta e cercare tutti i dati necessari per soddisfare le esigenze del cliente.

Ci sono tonnellate di diverse implementazioni di server GraphQL per ogni lingua possibile.

Apollo Server è un'implementazione del server GraphQL per JavaScript, in particolare per la piattaforma Node.js.

Supporta molti framework Node.js popolari, tra cui:

  • Esprimere
  • Hapi
  • Koa
  • Restify

In pratica, Apollo Server ci offre tre cose:

  • Un modo per descrivere i nostri dati con uno schema.
  • Il framework per i resolver, che sono funzioni che scriviamo per recuperare i dati necessari per soddisfare una richiesta.
  • Facilita la gestione dell'autenticazione per la nostra API.

Per motivi di apprendimento delle basi di Apollo Server, non utilizzeremo nessuno dei framework Node.js supportati. Invece, useremo qualcosa che è stato creato dal team Apollo, qualcosa di veramente grande che sarà la base del nostro apprendimento: Launchpad.

Trampolino di lancio

Launchpad è un progetto che fa parte dell'ombrello dei prodotti Apollo ed è uno strumento piuttosto sorprendente che ci consente di scrivere codice sul cloud e creare un Apollo Server online, proprio come avremmo eseguito uno snippet di codice su Codepen, JSFiddle o JSBin.

Tranne il fatto che invece di creare uno strumento visivo che verrà isolato lì, e inteso solo come una vetrina o come strumento di apprendimento, con Launchpad creiamo un'API GraphQL. Sarà accessibile al pubblico.

Ogni progetto su Launchpad è chiamato pad e ha il suo URL endpoint GraphQL, come:

https://1jzxrj129.lp.gql.zone/graphql

Una volta creato un pad, Launchpad ti dà la possibilità di scaricare il codice completo dell'app Node.js che lo sta eseguendo e devi solo eseguire npm install e npm start per avere una copia locale del tuo Apollo GraphQL Server.

Per riassumere, è un ottimo strumento per imparare, condividere e prototipare.

Il Server Apollo Hello World

Ogni volta che crei un nuovo Launchpad pad, ti viene presentato Hello, World! di Apollo Server. Immergiamoci.

Innanzitutto importare la funzione makeExecutableSchema da graphql-tools.

importare {makeExecutableSchema} da "graphql-tools"

Questa funzione viene utilizzata per creare un oggetto GraphQLSchema, fornendo una definizione dello schema (scritta nel linguaggio dello schema GraphQL) e un insieme di resolver.

Una definizione di schema è una stringa letterale del modello che contiene la descrizione della nostra query e i tipi associati a ciascun campo:

const typeDefs = `
  digitare query {
    ciao: stringa
  }
`

Un resolver è un oggetto che mappa i campi nello schema alle funzioni del resolver. È in grado di cercare dati per rispondere a una query.

Ecco un semplice resolver che contiene la funzione resolver per il campo hello, che restituisce semplicemente il mondo Hello! corda:

const resolvers = {
  Query: {
    ciao: (root, args, contesto) => {
      return "Ciao mondo!"
    }
  }
}

Dati questi due elementi, la definizione dello schema e il resolver, utilizziamo la funzione makeExecutableSchema che abbiamo importato in precedenza per ottenere un oggetto GraphQLSchema, che assegniamo alla const dello schema.

export const schema = makeExecutableSchema ({typeDefs, resolvers})

Questo è tutto ciò che serve per servire una semplice API di sola lettura. Launchpad si prende cura dei piccoli dettagli.

Ecco il codice completo per il semplice esempio Hello World:

importare {makeExecutableSchema} da "graphql-tools"

const typeDefs = `
  digitare query {
    ciao: stringa
  }
`

const resolvers = {
  Query: {
    ciao: (root, args, contesto) => {
      return "Ciao mondo!"
    }
  }
}

export const schema = makeExecutableSchema ({
  typedef,
  risolutori
})

Launchpad offre un ottimo strumento integrato per utilizzare l'API:

E come ho detto in precedenza, l'API è accessibile pubblicamente, quindi devi solo accedere e salvare il tuo pad.

Ho creato un pad che espone il suo endpoint su https://kqwwkp0pr7.lp.gql.zone/graphql, quindi proviamo usando curl dalla riga di comando:

$ curl \
  -X POST \
  -H "Tipo di contenuto: application / json" \
  --data '{"query": "{hello}"}' \
  https://kqwwkp0pr7.lp.gql.zone/graphql

che ci dà con successo il risultato che ci aspettiamo:

{
  "dati": {
    "ciao": "Ciao mondo!"
  }
}

Esegui il server GraphQL localmente

Abbiamo detto che tutto ciò che crei su Launchpad è scaricabile, quindi continuiamo.

Il pacchetto è composto da due file. Il primo, schema.js è quello che abbiamo sopra.

Il secondo, server.js, era invisibile in Launchpad e questo è ciò che fornisce la funzionalità Apollo Server sottostante, basata su Express, il popolare framework Node.js.

Non è l'esempio più semplice di un'installazione di Apollo Server, quindi per motivi di spiegazione, lo sostituirò con un esempio più semplice (ma sentiti libero di studiare che dopo aver compreso le basi).

Il tuo primo codice Apollo Server

Innanzitutto, esegui npm install e npm start sul codice Launchpad scaricato.

Il server nodo che abbiamo inizializzato in precedenza utilizza nodemon per riavviare il server quando i file cambiano, quindi quando si modifica il codice, il server viene riavviato con le modifiche applicate.

Aggiungi questo codice in server.js:

const express = require ('express')
const bodyParser = require ('body-parser')
const {graphqlExpress} = require ('apollo-server-express')
const {schema} = request ('./ schema')

const server = express ()

server.use ('/ graphql', bodyParser.json (), graphqlExpress ({schema}))

server.listen (3000, () => {
  console.log ('Ascolto GraphQL su http: // localhost: 3000 / graphql')
})

Con solo 11 righe, questo è molto più semplice del server configurato da Launchpad, perché abbiamo rimosso tutte le cose che hanno reso quel codice più flessibile per le loro esigenze.

La codifica ti obbliga a prendere decisioni difficili: quanta flessibilità hai bisogno ora? Quanto è importante avere un codice chiaro e comprensibile che puoi raccogliere tra sei mesi e facilmente modificare, o passare ad altri sviluppatori e membri del team in modo che possano essere produttivi nel minor tempo necessario?

Ecco cosa fa il codice:

Per prima cosa importiamo alcune librerie che useremo.

  • express che alimenterà la funzionalità di rete sottostante per esporre l'endpoint
  • bodyParser è il middleware di analisi del corpo del nodo
  • graphqlExpress è l'oggetto Apollo Server per Express
const express = require ('express')
const bodyParser = require ('body-parser')
const {graphqlExpress} = require ('apollo-server-express')

Successivamente importiamo l'oggetto GraphQLSchema che abbiamo creato nel file schema.js sopra come Schema:

const {schema} = request ('./ schema')

Ecco alcuni set Express standard e inizializziamo un server sulla porta 3000

const server = express ()

Ora siamo pronti per inizializzare Apollo Server:

graphqlExpress ({schema})

e lo passiamo come callback al nostro endpoint alle richieste HTTP JSON:

server.use ('/ graphql', bodyParser.json (), graphqlExpress ({schema}))

Tutto ciò di cui abbiamo bisogno ora è avviare Express:

server.listen (3000, () => {
  console.log ('Ascolto GraphQL su http: // localhost: 3000 / graphql')
})

Aggiungi un endpoint GraphiQL

Se si utilizza GraphiQL, è possibile aggiungere facilmente un endpoint / graphiql, da utilizzare con l'IDE interattivo nel browser GraphiQL:

server.use ('/ graphiql', graphiqlExpress ({
  endpointURL: '/ graphql',
  query: ``
}))

Ora non ci resta che avviare il server Express:

server.listen (PORT, () => {
  console.log ('Ascolto GraphQL su http: // localhost: 3000 / graphql')
  console.log ('Ascolto di GraphiQL su http: // localhost: 3000 / graphiql')
})

Puoi testarlo usando di nuovo l'arricciatura:

$ curl \
  -X POST \
  -H "Tipo di contenuto: application / json" \
  --data '{"query": "{hello}"}' \
  http: // localhost: 3000 / graphql

Questo ti darà lo stesso risultato di cui sopra, dove hai chiamato i server Launchpad:

{
  "dati": {
    "ciao": "Ciao mondo!"
  }
}
Ti interessa imparare JavaScript? Ottieni il mio ebook gratuito su jshandbook.com