Introduzione ad Apollo: la libreria per GraphQL

Apollo è la libreria per GraphQL più conosciuta.Scopriamo come funziona e le caratteristiche principali di Apollo Client e Server.

Introduzione ad Apollo: la libreria per GraphQL

Che cos'è Apollo e quali sono le sue componenti core

L’introduzione di GraphQL nel mondo del web development ha cambiato per sempre il modo con cui far dialogare server e client.
GraphQL permette infatti non solo di far decidere al client di quali dettagli ha bisogno in una specifica chiamata, ma anche di migliorare le prestazioni del nostro applicativo in termini di chiamate alla rete.
Questo linguaggio è una grande rivoluzione e va a sostituire i servizi REST.
Ma proprio perché GraphQL è solo un linguaggio, abbiamo bisogno di una implementazione da poter applicare ai nostri progetti.
Questa implementazione può essere fornita da diverse librerie, ma la più conosciuta, sviluppata e usata, è senza ombra di dubbio Apollo.
Apollo è una piattaforma costituita da più componenti, e la combinazione di questi crea un ecosistema che può essere sfruttato in toto, oppure solo in parte, andandosi a integrare con possibili strutture preesistenti.
I due componenti core, su cui si basa tutta la struttura sono Apollo Client e Apollo Server.

Apollo Client come funziona e i suoi vantaggi

Apollo Client è una libreria che nasce per gestire lo state management sia locale sia di dati remoti con GraphQL. Viene usata per fetching, cache dei dati e dati di applicazione. 
Ecco i suoi più grandi vantaggi:

  • Fetch di dati dichiarativo: ci permette di capire se la ricezione dei dati è in corso, se essi siano presenti oppure se si sia verificato un errore
  • Adattabile a ogni API GraphQL
  • Iniettabile in ogni applicativo JS: esistono wrapper per tutti i framework JS più usati, come React, Angular e Vue.

Come implementare Apollo Client su React

Analizziamo un esempio di implementazione di Apollo Client su React.
Come primo passaggio per poter permettere l'integrazione, installiamo due pacchetti necessari:

yarn add @apollo/client graphql

Il primo pacchetto comprende tutto ciò di cui abbiamo bisogno, incluso un wrapper per eseguire i vari step su React.
Il secondo è un'utility che fornisce le logiche per l'interpretazione delle query Graphql.
Ora dobbiamo inizializzare un nuovo client. Per fare ciò, andiamo nel file index.js di React, importiamo i pacchetti necessari e creiamo un costruttore per l'inizializzazione.
Apollo Client sarà il costruttore a cui assegneremo l'url del server Graphql. Possiamo inoltre aggiungere un parametro cache, a cui assegneremo una nuova istanza di InMemoryCache.In questo modo, avremo la possibilità di sfruttare la cache interna per velocizzare la ricezione dei dati.

import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
   uri: 'GRAPHQL_SERVER_URI',
   cache: new InMemoryCache()
});

Per connettere Apollo a React abbiamo bisogno di un wrapper. Questo ci viene offerto dalla libreria e viene chiamato Apollo Provider.
Funziona esattamente come un provider di React Context e rende fruibile l'uso di Apollo all'interno di tutta l'applicazione.
Viene posizionato solitamente nel punto più alto possibile dell'albero. Al provider dovremo passare come prop l'istanza di client che abbiamo creato in precedenza.

import React from 'react';
import { render } from 'react-dom';

import { ApolloProvider } from '@apollo/client';

function App() {
   return (
     <ApolloProvider client={client}>
          <div>
             <h2>My first Apollo app 🚀</h2>
         </div>
 </ApolloProvider>
 );
}

render(<App />, document.getElementById('root'));

Dopo aver collegato e agganciato Apollo a React, possiamo infine creare e sfruttare la nostra prima query.
Per fare ciò, utilizziamo useQuery (funzione basata sulle Hook API) che ci permette di gestire 3 stati nella nostra ricezione di dati, estrapolati dalla dichiarazione dell' hook:

  • Loading: la nostra query è in corso, non abbiamo dati
  • Error: la query è fallita
  • Data: la query è finita e abbiamo i dati richiesti
import { useQuery, gql } from '@apollo/client';

const EXCHANGE_RATES = gql`
   query GetExchangeRates {
       rates(currency: "USD") {
         currency
         rate
        }
      }
`;

function ExchangeRates() {
   const { loading, error, data } = useQuery(EXCHANGE_RATES);
   
   if (loading) return <p>Loading...</p>;
   if (error) return <p>Error :(</p>;

   return data.rates.map(({ currency, rate }) => (
      <div key={currency}>
          <p>
              {currency}: {rate}
          </p>
        </div>
    ));
}

Qui possiamo notare 3 parti di codice. Successivamente:

  1.  Andiamo a importare dalla libreria l'hook e un'utility di creazione query
  2. Con l'utility creiamo la query che ci serve
  3. Nella funzione di renderizzazione usiamo l'hook, passando in input la query creata e ricevendo in output i 3 stati, gestiti nell'ultima parte della funzione.

Apollo Server che cos'è e perché è consigliato per dialogare con il frontend

Apollo Server è un'implementazione lato server di GraphQL scritta in JS.
Non è obbligatorio il suo utilizzo in caso si voglia sfruttare Apollo Client, ma è invece caldamente consigliato nel caso in cui si voglia creare una struttura solida per dialogare con il frontend.
Apollo Server viene infatti considerato come implementazione standard quando si usa GQL, per diversi motivi, tra cui:

  • Lo scambio di dati testato e solido tra le due librerie
  • La creazione di strumenti utili da parte della community
  • La facile integrazione della libreria con i framework più popolari, dove per ognuno troviamo un modulo sviluppato appositamente per collegare le funzionalità di uno e dell’altro.

In questo articolo andremo a scoprire come utilizzare Apollo Server con Express e perché è il framework più utilizzato lato server.

Come usare Apollo Server con Express

In una cartella, inizializziamo un nuovo progetto.

mkdir apollo-server-sample
cd apollo-server-sample && yarn init

Successivamente, andiamo a installare due dipendenze fondamentali:

yarn add apollo-server-express dotenv

La prima è il wrapper che farà dialogare il framework e la libreria, mentre, la seconda ci permette di creare un file .env, dove andremo a salvare alcune variabili utili.
I file che creeremo saranno tre, che comporranno una prima implementazione molto basica, ma su cui possiamo già vedere i punti cardine.
Il primo, chiamato molto semplicemente server.js, avrà al suo interno l'implementazione vera e propria della libreria.
Qui andremo a dichiarare una nuova istanza di Apollo Server, andremo ad assegnare con l'utilty applyMiddleware la nuova istanza di Express e attenderemo altre richieste.
Due opzioni molto importanti sono le corsOption, che ci permettono di impostare il pacchetto CORS, e il context, nel caso in cui volessimo far accedere al nostro server solo con un token di autorizzazione.

require('dotenv').config();
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const { typeDefs } = require("./schema");
const { resolvers } = require("./resolvers");

const corsOptions = {
   origin: "http://localhost:3000",
   credentials: true,
};

const server = new ApolloServer({
   typeDefs,
   resolvers,
   cors: corsOptions,
});

const app = express();
server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
    console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);

Nel file schema.js, procediamo a creare ed exportare la definizione di tutti i tipi. Ogni oggetto su cui potremo fare le nostre query e mutations avrà degli attributi, che andremo a dichiarare e assegnare al server. Anche le stesse query e mutation avranno dei tipi, da dichiarare nello stesso punto.
L'utility gql ci permette di tradurre da linguaggio GraphQL a linguaggio GraphQL AST, una struttura leggibile e lavorabile dalla sottostante virtual machine JS.

const { gql } = require("apollo-server-express");

exports.typeDefs = gql`
    type Query {
       hello: String
    }
`

Infine, andiamo a creare il file resolvers.js, dove regoliamo il comportamento delle singole query e mutation. In questo caso, la nostra query hello ci risponderà una stringa.

exports.resolvers = {
   Query: {
   hello: () => 'Hello World!',
 }
};

Avendo nel file server assegnato all' istanza la porta 4000, possiamo, dopo aver fatto partire il server, spostarci sul browser, all'indirizzo http://localhost:4000/graphql dove ci troveremo di fronte GraphQL Playground, utility messa a disposizione da Apollo per provare le nostre nuove api.

Conclusioni

Abbiamo scoperto: le caratteristiche più importanti di Apollo, la libreria per GraphQL più conosciuta e utilizzata dai developers, come avviene l'implementazione di Apollo Client su React e quella di Apollo Server su Express.

Hai qualche domanda o dubbio? Contattaci!