Tutorial sobre cómo hacer un chat con Socket.IO y Angular 21
Tiempos estimado de lectura: 8 min
- Backend Node.js + Socket.IO
- Frontend Angular 21 con Signals y Standalone Components
- Enfoque en seguridad y escalabilidad
Tabla de contenidos:
- Arquitectura mínima y objetivos
- Servidor Node.js (ESM, Socket.IO)
- Servicio Angular 21 con Signals
- Componente Standalone de Angular
- Llevarlo a producción: checklist técnica
- Integración con automatizaciones y agentes
- Conclusión
Arquitectura mínima y objetivos
Queremos un chat en tiempo real con:
- Backend Node.js + Socket.IO (WebSocket con fallback). (socket.io)
- Frontend Angular 21 usando Signals y Standalone Components (angular.io/guide/signals).
- Código claro, escalable y preparado para integrarse en workflows (por ejemplo con n8n: n8n.io).
Puntos críticos: reconexión, persistencia de historial, autenticación en el handshake, y escalado horizontal (Redis adapter).
1. Servidor Node.js (ESM, Socket.IO)
Servidor básico que reemite mensajes a todos los clientes. Valida siempre payloads y añade ACKs:
// server.ts (ESM)
import http from 'http';
import express from 'express';
import { Server } from 'socket.io';
import cors from 'cors';
const app = express();
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
cors: { origin: 'http://localhost:4200' }
});
io.on('connection', socket => {
console.log('connected', socket.id);
socket.on('chat:send', (payload, ack) => {
// Validación mínima
if (!payload?.text || typeof payload.text !== 'string') {
return ack?.({ status: 'error', reason: 'invalid_payload' });
}
const msg = { id: socket.id, text: payload.text, ts: Date.now() };
io.emit('chat:message', msg);
ack?.({ status: 'ok', id: msg.id, ts: msg.ts });
});
socket.on('disconnect', () => console.log('disconnected', socket.id));
});
server.listen(3000);
Buenas prácticas aquí: validar, usar ACKs y no confiar en el cliente para metadatos críticos.
2. Servicio Angular 21 con Signals (client)
Encapsula Socket.IO en un servicio. Usamos un WritableSignal para mensajes; la UI lee la señal directamente sin pipes ni suscripciones manuales.
// src/app/services/chat.service.ts
import { Injectable, signal, WritableSignal } from '@angular/core';
import { io, Socket } from 'socket.io-client';
export interface ChatMessage { id: string; text: string; ts: number }
@Injectable({ providedIn: 'root' })
export class ChatService {
private socket: Socket;
public messages: WritableSignal = signal([]);
constructor() {
this.socket = io('http://localhost:3000', { transports: ['websocket'] });
this.socket.on('chat:message', (m: ChatMessage) => {
this.messages.update(cur => [...cur, m]);
});
}
send(text: string) {
return new Promise((resolve, reject) => {
this.socket.emit('chat:send', { text }, (res: any) => {
res?.status === 'ok' ? resolve(res) : reject(res);
});
});
}
disconnect() { this.socket.disconnect(); }
}
Signals ofrecen lectura sin async pipes y actualizaciones finas del DOM (ideal para listas largas).
3. Componente Standalone de Angular
Standalone Component que consume el servicio:
// src/app/chat/chat.component.ts (Standalone)
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ChatService } from '../services/chat.service';
@Component({
standalone: true,
imports: [CommonModule, FormsModule],
selector: 'app-chat',
template: `
{{ m.id | slice:0:6 }}: {{ m.text }} {{ m.ts | date:'HH:mm:ss' }}
`
})
export class ChatComponent {
chat = inject(ChatService);
text = '';
async send() {
const t = this.text.trim(); if (!t) return;
try { await this.chat.send(t); this.text = ''; } catch { /* manejar error */ }
}
}
4. Llevarlo a producción: checklist técnica
- Escalado: usa Redis adapter para Socket.IO en múltiples instancias (socket.io/docs/v4/using-multiple-nodes).
- Persistencia: guarda mensajes en DB (Mongo/Postgres) y carga historial en conexión.
- Autenticación: valida JWT en el handshake con
io.use((socket, next) => ...). - Rooms & namespaces: separa conversaciones y reduce broadcast innecesario.
- Observabilidad: métricas de hit-rate, latencia, reconexiones.
- Seguridad: rate-limiting por socket, sanitización de texto, validación de tamaño.
5. Integración con automatizaciones y agentes
En entornos productivos el chat suele disparar acciones: crear tickets, invocar agentes de IA o lanzar workflows. Aquí entra el valor de orquestación con n8n. En Dominicode Labs documentamos blueprints para:
- Exponer eventos de chat a n8n via webhook/Redis.
- Enriquecer mensajes con agentes de IA que clasifican o responden automáticamente.
- Ejecutar pipelines (crear ticket, notificar Slack, persistir metadatos).
Dominicode Labs tiene plantillas y ejemplos de arquitectura para conectar Socket.IO con workflows productivos sin acoplar la lógica de negocio dentro del servidor de sockets.
Conclusión
Este tutorial sobre cómo hacer un chat con Socket.IO y Angular 21 muestra un camino claro: Signals + Standalone components simplifican el front; Socket.IO gestiona el transporte; Redis, persistencia y autenticación convierten el prototipo en sistema robusto. Si tu objetivo es más que “un chat que funciona” —si quieres que el chat forme parte de procesos automatizados en producción— diseña la integración con workflows y agentes desde el principio.
FAQ
- ¿Qué es Socket.IO?
- ¿Qué son señales en Angular?
- ¿Qué son los componentes standalones?
- ¿Cómo es la implementación en producción?
- ¿Cuáles son las ventajas de utilizar n8n?
Socket.IO es una biblioteca que permite la comunicación en tiempo real entre clientes y servidores utilizando WebSockets u otros transportes.
Las señales en Angular son una nueva forma de crear y gestionar el estado, permitiendo una comunicación eficiente entre componentes.
Los componentes standalones en Angular son componentes que no dependen de módulos para su funcionamiento, facilitando su reutilización.
La implementación en producción debe considerar aspectos como escalabilidad, persistencia, autenticación y seguridad.
n8n es una herramienta de automatización que permite conectar diferentes aplicaciones de forma visual y sencilla, optimizando flujos de trabajo.

Leave a Reply