Concepto clave
Las suscripciones GraphQL son una característica que permite a los clientes recibir actualizaciones en tiempo real cuando ocurren cambios específicos en los datos del servidor. A diferencia de las consultas y mutaciones tradicionales que siguen un modelo request-response, las suscripciones mantienen una conexión persistente usando WebSockets.
Imagina que estás en una sala de chat: en lugar de preguntar constantemente "¿hay mensajes nuevos?" (como haría una consulta tradicional), te suscribes al canal y recibes notificaciones automáticamente cuando alguien escribe. Apollo Server implementa esto mediante el protocolo GraphQL over WebSocket, que establece un canal bidireccional entre cliente y servidor.
Cómo funciona en la práctica
Para configurar suscripciones en Apollo Server con Next.js, necesitas tres componentes principales:
- Un servidor WebSocket que maneje las conexiones persistentes
- Un PubSub (publicador-suscriptor) que gestione los eventos
- Resolvers de suscripción que definan qué datos enviar
Paso a paso:
// 1. Configurar Apollo Server con soporte WebSocket
import { ApolloServer } from 'apollo-server-micro';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
subscriptions: {
path: '/api/graphql',
},
});
// 2. Crear instancia de WebSocketServer
const wsServer = new WebSocketServer({
server: httpServer,
path: '/api/graphql',
});
// 3. Conectar WebSocket con Apollo
useServer({ schema }, wsServer);Caso de estudio
Implementemos un sistema de notificaciones en tiempo real para una aplicación de gestión de proyectos. Cuando un usuario asigna una nueva tarea, todos los miembros del equipo reciben una notificación inmediata.
| Componente | Implementación |
|---|---|
| TypeDefs | |
| PubSub | |
| Resolver de mutación | |
| Resolver de suscripción | |
El filtro (withFilter) es crucial para evitar que los usuarios reciban notificaciones de proyectos a los que no pertenecen.
Errores comunes
- Olvidar configurar CORS para WebSockets: Los navegadores bloquean conexiones WebSocket desde dominios no autorizados. Configura CORS tanto para HTTP como para WebSocket.
- No manejar reconexiones: Las conexiones WebSocket pueden fallar. Implementa lógica de reconexión en el cliente con backoff exponencial.
- Filtrar mal los eventos: Sin filtros adecuados, los usuarios reciben datos que no les corresponden, comprometiendo seguridad y rendimiento.
- Ignorar el escalado horizontal: PubSub en memoria no funciona con múltiples instancias del servidor. Para producción, usa Redis PubSub.
- No limpiar suscripciones: En React/Next.js, debes limpiar las suscripciones en useEffect para evitar memory leaks.
Checklist de dominio
- ¿Puedes configurar Apollo Server con soporte WebSocket en Next.js?
- ¿Sabes implementar un resolver de suscripción con filtros?
- ¿Entiendes la diferencia entre pubsub.publish() y pubsub.asyncIterator()?
- ¿Puedes conectar un cliente Apollo a suscripciones desde React?
- ¿Sabes manejar errores de conexión WebSocket?
- ¿Puedes escalar suscripciones usando Redis en producción?
- ¿Entiendes cuándo usar suscripciones vs polling vs Server-Sent Events?
Implementar un chat en tiempo real con GraphQL Subscriptions
Crea un sistema de chat básico donde los usuarios puedan enviar mensajes y ver los mensajes de otros en tiempo real.
- Configura Apollo Server en Next.js con soporte para WebSockets
- Define los tipos GraphQL necesarios:
- Mensaje: id, contenido, usuario, timestamp
- Mutation: enviarMensaje(contenido: String!, usuario: String!): Mensaje
- Subscription: mensajeEnviado: Mensaje
- Implementa el resolver para la mutación enviarMensaje que publique el evento
- Implementa el resolver para la suscripción mensajeEnviado
- Crea un componente React que:
- Muestre los mensajes existentes
- Permita enviar nuevos mensajes
- Se suscriba para recibir mensajes nuevos en tiempo real
- Prueba abriendo dos pestañas del navegador y enviando mensajes desde ambas
- Usa graphql-ws para el servidor WebSocket
- Recuerda limpiar la suscripción en el cleanup de useEffect
- El timestamp puede generarse con new Date().toISOString()
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.