Introduzione alle Sottoscrizioni in GraphQL: Aggiornamenti in Tempo Reale
Le sottoscrizioni (subscriptions) in GraphQL sono una delle funzionalità più potenti per abilitare aggiornamenti in tempo reale nelle applicazioni. Con le subscriptions, il server può inviare dati al client in tempo reale, senza che il client debba effettuare richieste ripetitive (polling). Questa funzionalità è particolarmente utile in applicazioni come chat, sistemi di notifiche o dashboard live, dove è necessario ricevere dati aggiornati non appena un evento avviene.
In questo articolo esploreremo cosa sono le sottoscrizioni in GraphQL, come funzionano e come implementarle utilizzando Apollo Server.
Cosa Sono le Sottoscrizioni in GraphQL?
Le sottoscrizioni in GraphQL sono un meccanismo che consente al client di iscriversi a determinati eventi e ricevere aggiornamenti in tempo reale dal server. A differenza delle query e delle mutazioni, che seguono un modello di richiesta-risposta, le sottoscrizioni mantengono una connessione aperta e inviano dati al client ogni volta che si verifica un evento pertinente.
Le sottoscrizioni utilizzano generalmente WebSocket per mantenere una connessione persistente tra il client e il server.
Esempio di Schema di Sottoscrizione
Immagina un’applicazione di messaggistica in cui gli utenti possono inviare messaggi in tempo reale. Lo schema GraphQL potrebbe includere una subscription per ricevere i nuovi messaggi:
type Subscription {
messageAdded: Message
}
type Message {
id: ID!
content: String!
sender: String!
}
Con questa subscription, il client può iscriversi per ricevere nuovi messaggi in tempo reale quando vengono aggiunti al sistema.
Come Funzionano le Sottoscrizioni
Le sottoscrizioni funzionano creando una connessione persistente tra il client e il server utilizzando WebSocket o altri protocolli di comunicazione in tempo reale. Ecco i passaggi principali:
- Il Client si Sottoscrive: Il client invia una richiesta di sottoscrizione per uno specifico evento (ad esempio,
messageAdded
). - Il Server Invia Aggiornamenti: Quando l’evento si verifica, il server invia i dati aggiornati al client attraverso la connessione WebSocket.
- Il Client Riceve i Dati in Tempo Reale: Il client può visualizzare i dati non appena sono disponibili, senza la necessità di inviare ulteriori richieste.
Implementazione delle Sottoscrizioni in Apollo Server
Per implementare le sottoscrizioni in GraphQL con Apollo Server, devi configurare WebSocket insieme al protocollo HTTP per le query e le mutazioni.
Step 1: Installazione delle Dipendenze
Assicurati di avere Apollo Server e le dipendenze WebSocket installate:
npm install apollo-server graphql graphql-subscriptions ws
- apollo-server: Per configurare Apollo Server.
- graphql-subscriptions: Fornisce un sistema di pubblicazione/sottoscrizione per le subscriptions.
- ws: Un’implementazione WebSocket per Node.js.
Step 2: Configurazione di Apollo Server con WebSocket
Crea un server che supporti sia le query/mutazioni HTTP che le sottoscrizioni WebSocket.
const { ApolloServer, gql } = require("apollo-server");
const { PubSub } = require("graphql-subscriptions");
const { createServer } = require("http");
const { WebSocketServer } = require("ws");
const { useServer } = require("graphql-ws/lib/use/ws");
// Inizializza PubSub per gestire gli eventi di sottoscrizione
const pubsub = new PubSub();
// Definisci lo schema GraphQL
const typeDefs = gql`
type Message {
id: ID!
content: String!
sender: String!
}
type Query {
messages: [Message]
}
type Mutation {
addMessage(content: String!, sender: String!): Message
}
type Subscription {
messageAdded: Message
}
`;
// Simula un database in memoria
let messages = [];
let messageId = 1;
// Definisci i resolver
const resolvers = {
Query: {
messages: () => messages,
},
Mutation: {
addMessage: (_, { content, sender }) => {
const message = { id: messageId++, content, sender };
messages.push(message);
pubsub.publish("MESSAGE_ADDED", { messageAdded: message });
return message;
},
},
Subscription: {
messageAdded: {
subscribe: () => pubsub.asyncIterator(["MESSAGE_ADDED"]),
},
},
};
// Crea il server HTTP
const httpServer = createServer();
// Inizializza WebSocket Server per le sottoscrizioni
const wsServer = new WebSocketServer({
server: httpServer,
path: "/graphql",
});
// Usa il WebSocket server con Apollo
useServer(
{ schema: new ApolloServer({ typeDefs, resolvers }).schema },
wsServer
);
// Avvia il server HTTP
httpServer.listen(4000, () => {
console.log("Server is running on http://localhost:4000/graphql");
});
Spiegazione del Codice
- PubSub: Un’implementazione in memoria per la pubblicazione/sottoscrizione di eventi. Questo esempio utilizza
PubSub
per inviare notifiche ai client quando viene aggiunto un nuovo messaggio. - messageAdded Subscription: Il client può iscriversi a questa subscription per ricevere nuovi messaggi in tempo reale.
- WebSocket Server: Utilizza WebSocket per gestire le connessioni persistenti per le subscriptions.
Step 3: Configurazione del Client con Apollo Client
Il client può utilizzare Apollo Client per sottoscriversi agli aggiornamenti in tempo reale.
Installazione delle Dipendenze Client
npm install @apollo/client graphql-ws
Configurazione di Apollo Client per le Sottoscrizioni
Configura il client per utilizzare WebSocket:
import { ApolloClient, InMemoryCache, split, HttpLink } from "@apollo/client";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";
import { getMainDefinition } from "@apollo/client/utilities";
// Configura il link HTTP
const httpLink = new HttpLink({
uri: "http://localhost:4000/graphql",
});
// Configura il link WebSocket per le subscriptions
const wsLink = new GraphQLWsLink(
createClient({
url: "ws://localhost:4000/graphql",
})
);
// Usa split per instradare le query HTTP e le subscriptions WebSocket
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === "OperationDefinition" &&
definition.operation === "subscription"
);
},
wsLink,
httpLink
);
// Configura Apollo Client
const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache(),
});
Step 4: Sottoscrizione agli Aggiornamenti in Tempo Reale
Nel componente React, utilizza useSubscription
per iscriversi alla subscription:
import { gql, useSubscription } from "@apollo/client";
const MESSAGE_ADDED_SUBSCRIPTION = gql`
subscription OnMessageAdded {
messageAdded {
id
content
sender
}
}
`;
function MessageList() {
const { data, loading } = useSubscription(MESSAGE_ADDED_SUBSCRIPTION);
if (loading) return <p>Loading...</p>;
return (
<ul>
{data?.messageAdded && (
<li>
{data.messageAdded.sender}: {data.messageAdded.content}
</li>
)}
</ul>
);
}
export default MessageList;
Best Practices per le Sottoscrizioni
- Limita le Sottoscrizioni: Utilizza le subscriptions solo quando necessario, poiché mantengono connessioni persistenti che possono aumentare il carico sul server.
- Autenticazione nelle Sottoscrizioni: Implementa la gestione dell’autenticazione anche nelle sottoscrizioni per proteggere le informazioni sensibili.
- Gestione della Connessione: Gestisci correttamente la disconnessione e il recupero della connessione nel client per garantire che l’applicazione sia resiliente.
- ScalabilitĂ : Se il carico di lavoro aumenta, utilizza strumenti di messaggistica piĂą avanzati come Redis o Kafka per scalare il sistema di pubblicazione/sottoscrizione.
Conclusione
Le sottoscrizioni in GraphQL forniscono un modo potente per implementare aggiornamenti in tempo reale nelle applicazioni. Con Apollo Server e Apollo Client, puoi facilmente configurare un sistema di sottoscrizione che utilizza WebSocket per inviare aggiornamenti contin
ui ai client. Questo ti permette di costruire applicazioni interattive e reattive, dove gli utenti possono ricevere aggiornamenti in tempo reale senza dover aggiornare la pagina o inviare richieste continue.
Sfruttando la potenza delle subscriptions in GraphQL, puoi migliorare significativamente l’esperienza utente, specialmente in applicazioni come chat, notifiche o dashboard in tempo reale.