Esta aplicación combina frontend estático (HTML, CSS, JS) y un backend en Node.js con Express y WebSockets nativos (librería ws). Está lista para ejecutarse localmente o desplegarse en cualquier servidor que soporte Node.js.
/mi-app
│
├─ server.js # Servidor Express + WebSocket
├─ package.json
└─ public/ # Frontend estático
└─ index.html # HTML + CSS + JS inline (WebRTC y WebSocket)
- public/: Carpeta con todo el frontend.
- server.js: Backend que sirve archivos estáticos y maneja WebSockets.
-
Node.js 24.22.1+ (LTS; también válido 22.23.4+ o 26.12.1+)
-
NPM
-
Dependencias del proyecto (
expressyws):npm install
.nvmrcfija Node 24.22.1 y.npmrcactivaengine-strict:npm installfalla si el host no usa un parche seguro. Node 18 y 20 están EOL y no deben usarse.
- Clona el repositorio o descarga el proyecto.
- Instala las dependencias:
npm install- Ejecuta el servidor:
node server.jsNota: abre la app desde el propio servidor (
http://localhost:3000). No usesnpx serve .: solo sirve archivos estáticos y deja sin backend ni WebSocket.
-
Abre tu navegador en http://localhost:3000
El puerto se toma de
process.env.PORT(por defecto 3000).
- Sube todo el proyecto al servidor que soporte Node.js.
- Asegúrate de instalar dependencias con
npm install. - Ejecuta el servidor usando
node server.jso un gestor de procesos como PM2. - Si usas un servicio que asigna el puerto automáticamente (Render, Heroku, Railway, Fly.io, etc.):
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => console.log(`Servidor corriendo en puerto ${PORT}`));- Abre la URL pública del servidor para acceder al frontend.
Runtime del host: Node 22.23.4+, 24.22.1+ o 26.12.1+. Está declarado en
package.json(engines) y.nvmrc; Render y Railway lo respetan automáticamente. No uses Node 18/20: están fuera de soporte y sin parches de seguridad.
El frontend abre la conexión en public/index.html (script inline), usando el mismo host que sirve la página:
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const ws = new WebSocket(`${wsProtocol}//${window.location.host}`);
ws.onopen = () => ws.send(JSON.stringify({ type: 'join', roomId: 'sala-123' }));
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Mensaje del servidor:', data);
};- No hay que cambiar la URL: se conecta al mismo dominio/host y usa
wss://automáticamente si la página va por HTTPS. - El servidor solo reenvía los mensajes
joinysignalal resto de la sala.
- Asegúrate de que la carpeta public/ exista y contenga
index.html. - Para SPA (rutas internas en frontend) con Express 5, usa un comodín con nombre:
app.get('/*splat', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});- No uses
npx serve .para ejecutar la app, ya que solo sirve archivos estáticos y no ejecuta el backend ni WebSockets. - Este proyecto funciona tanto en local como en cualquier servidor Node.js compatible.
¡Eso es todo! Al abrir la URL de tu servidor deberías ver tu aplicación funcionando con WebSockets activos.