BroadcastChannel vs window.open: cómo comunicar ventanas en el navegador
Comunicar dos pestañas o ventanas del navegador que están bajo el mismo dominio suena a tarea sencilla. Pero en la práctica hay dos APIs que compiten para resolverlo, cada una con fortalezas y casos de uso distintos: BroadcastChannel y window.open + postMessage.
La pregunta no es cuál es mejor, sino cuál necesitas según lo que quieras hacer.
BroadcastChannel: el bus de mensajes del navegador
BroadcastChannel es una API relativamente moderna (2016, pero bien soportada desde 2020) que permite a cualquier contexto de navegación —pestañas, iframes, workers— del mismo origen comunicarse a través de un canal nombre.
// Canal compartido
const canal = new BroadcastChannel('notificaciones')
// Escuchar
canal.onmessage = (e) => console.log('Recibido:', e.data)
// Emitir (cualquier pestaña conectada al mismo canal lo recibe)
canal.postMessage('¡Hola a todas las pestañas!')
Características clave:
- Multidireccional. Un mensaje lo reciben todas las pestañas conectadas al canal. No hay emisor/receptor fijo.
- Sin relación jerárquica. No importa quién abrió a quién. Cualquier pestaña puede unirse al canal.
- Mismo origen obligatorio. No funciona entre dominios distintos.
- Lifecycle automático. El canal se limpia solo cuando todas las pestañas se cierran.
- API mínima. Dos métodos (
postMessage,close) y un evento (onmessage).
Cuándo usarlo
- Sincronizar estado entre pestañas (preferencias de tema, carrito de compra, sesión).
- Chats o notificaciones en tiempo real sin servidor.
- Cualquier patrón "publicar/suscribir" dentro del mismo origen.
Demo interactiva
Abre esta página en dos pestañas y envía mensajes entre ellas:
window.open + postMessage: control 1:1 con relación jerárquica
window.open devuelve una referencia a la ventana hija, y con postMessage puedes enviarle mensajes. La hija responde usando window.opener.postMessage().
// Ventana padre
const hija = window.open('detalle.html', 'detalle', 'width=600,height=400')
// Enviar a la hija
hija.postMessage({ productoId: 42 }, 'https://midominio.com')
// Escuchar respuesta
window.addEventListener('message', (e) => {
if (e.origin !== 'https://midominio.com') return
console.log('Hija responde:', e.data)
})
// Ventana hija (detalle.html)
window.addEventListener('message', (e) => {
if (e.origin !== 'https://midominio.com') return
cargarProducto(e.data.productoId)
})
// Responder al padre
window.opener.postMessage({ tipo: 'comprado' }, 'https://midominio.com')
Características clave:
- Unidireccional por conexión. Una ventana habla con otra específica. Para llegar a N ventanas necesitas N referencias.
- Relación jerárquica. Quien abre tiene el control (puede cerrar la hija, reposicionarla, etc.).
- Soporta cross-origin. Usando
targetOriginpuedes comunicar ventanas de distintos dominios de forma segura. - Requiere gestión manual. Ventanas huérfanas, referencias rotas, limpieza de event listeners.
Cuándo usarlo
- Diálogos o ventanas modales abiertas desde la app (editor de imágenes, asistente de pago).
- Comunicación con iframes o ventanas de terceros (con
targetOriginrestringido). - Flujos donde la ventana padre necesita controlar el ciclo de vida de la hija.
Demo interactiva
La ventana padre abre una hija. La comunicación es 1:1 y el padre puede cerrar la hija:
Comparativa rápida
| Característica | BroadcastChannel | window.open + postMessage |
|---|---|---|
| Ámbito | Mismo origen | Cualquier origen (con targetOrigin seguro) |
| Dirección | Multidireccional (broadcast) | 1:1 (punto a punto) |
| Relación entre ventanas | Plana (canal) | Jerárquica (padre-hija) |
| Control de ventana | No | Sí (cerrar, enfocar, mover) |
| Complejidad | Baja | Media |
| Soporte navegadores | ~95% | ~100% |
| Ideal para | Sincronizar estado entre pestañas | Diálogos y flujo controlado |
Comparativa lado a lado
Ambas APIs funcionando simultáneamente en la misma página:
Conclusión
No elijas una API porque sea "más moderna". BroadcastChannel es perfecto cuando necesitas que varias pestañas del mismo origen se enteren de algo sin importar quién lo emitió. window.open + postMessage es mejor cuando necesitas controlar una ventana hija, trabajar con orígenes distintos, o mantener una relación 1:1 clara.
Úsalas juntas cuando tenga sentido. No son excluyentes.
Índice de demos