Web Workers: definición, casos de uso y ejemplos
Un Web Worker ejecuta JavaScript en un hilo en segundo plano para que la página siga receptiva. Cómo funciona, qué no puede hacer y cuándo compensa.
¿Qué es un Web Worker?
Un Web Worker es un archivo JavaScript que el navegador ejecuta en un hilo en segundo plano, separado del hilo principal que se encarga del renderizado y de la interacción del usuario. MDN lo describe como una forma de ejecutar scripts en hilos en segundo plano sin interferir con la interfaz de usuario. Trasladar ahí el trabajo pesado mantiene la página receptiva, lo que ayuda a métricas como Interaction to Next Paint (INP).
Cómo funcionan los Web Workers
La página crea un worker con new Worker("worker.js"). Ambos lados no comparten variables: se comunican enviando mensajes con postMessage y recibiéndolos en el evento message. Un worker no tiene acceso al DOM ni a los objetos de la página, así que no puede tocar lo que ve el usuario. Devuelve resultados y el hilo principal actualiza la página.
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ rows: largeArray });
worker.addEventListener('message', (event) => {
console.log('Result:', event.data);
});
// worker.js
self.addEventListener('message', (event) => {
const result = expensiveCompute(event.data.rows);
self.postMessage(result);
});
Tipos de workers
| Tipo | Para qué sirve |
|---|---|
| Worker dedicado | Lo usa solo el script que lo creó. La opción habitual. |
| Worker compartido | Accesible desde varios scripts, pestañas o frames del mismo origen, mediante un port. |
| Service worker | Un proxy entre la página, el navegador y la red, para uso sin conexión, caché, notificaciones push y sincronización en segundo plano. Consulta service workers. |
| Worklet | Un worker ligero para una tarea concreta, como el Audio Worklet para procesar audio. |
Qué puede y qué no puede hacer un worker
Los workers pueden usar fetch, WebSockets, IndexedDB y temporizadores, y cargar scripts con importScripts(). No pueden manipular el DOM ni usar partes de window; usa self en su lugar. localStorage es una función de window y no está disponible en los workers, así que usa IndexedDB para almacenar datos ahí. Consulta la guía de MDN sobre web workers y su lista de funciones disponibles antes de depender de una API.
Cuándo compensa un Web Worker
- Tareas largas. Según web.dev, una tarea que se ejecuta más de 50 ms en el hilo principal es una tarea larga. El trabajo que supera ese umbral con frecuencia es candidato.
- Analizar y transformar datos grandes, como archivos JSON, CSV o XML voluminosos.
- Criptografía y hashing que de otro modo congelarían la interfaz.
- Procesamiento de imágenes, audio y documentos, como redimensionar, comprimir u OCR.
- Descargas y sincronización en segundo plano mientras el usuario sigue trabajando.
Cómo pasar datos con eficiencia
Por defecto los mensajes se copian mediante clonado estructurado. Con cargas grandes, esa copia es el coste real. Los objetos transferibles, como un ArrayBuffer, pasan al otro lado con una transferencia sin copia y el original queda inutilizable:
const bytes = new Uint8Array(1024 * 1024 * 32);
worker.postMessage(bytes.buffer, [bytes.buffer]);
SharedArrayBuffer permite que los hilos usen la misma memoria, pero MDN advierte de problemas de determinismo, seguridad y rendimiento, así que úsalo solo si lo necesitas. Cuando un worker termina, llama a worker.terminate() desde el hilo principal para detenerlo de inmediato.
Ejemplo: una importación de CSV que va a tirones
Un panel analiza un CSV muy grande cuando el usuario lo suelta en la página. En el hilo principal la página se congela varios segundos, los clics se acumulan y el INP es malo. Si trasladas el analizador a un worker y devuelves los datos por bloques, la interfaz sigue fluida y puedes mostrar una barra de progreso. El análisis tarda lo mismo, pero el usuario puede seguir interactuando mientras se ejecuta.
Errores frecuentes
- Enviar objetos enormes una y otra vez. Clonar cuesta tiempo y memoria. Transfiere buffers o envía bloques más pequeños.
- Intentar tocar el DOM desde el worker. Lanza un error. Devuelve datos y actualiza la página en el hilo principal.
- Crear un worker por cada clic. Arrancar tiene un coste. Reutiliza un worker o un pequeño pool.
- Olvidar terminarlos. Los workers inactivos retienen memoria. Llama a
terminate()o deja que el worker se cierre solo. - Añadir un worker para tareas diminutas. Por debajo del umbral de tarea larga, la sobrecarga de mensajes suele superar la ganancia.
- Ignorar los errores. Escucha el evento
errordel worker o los fallos pasarán desapercibidos.
Web Workers, pruebas de rendimiento y monitorización
Los workers mejoran la capacidad de respuesta del front-end, así que mídela. web.dev describe el Total Blocking Time (TBT) como una métrica de laboratorio que suele correlacionar con un INP bajo y recomienda quedarse por debajo de 200 ms en hardware móvil medio. El INP es una métrica de campo: web.dev considera bueno un valor de 200 ms o menos en el percentil 75. La monitorización de velocidad de página de LoadFocus ejecuta Lighthouse desde varias ubicaciones para que sigas los resultados de laboratorio a lo largo del tiempo, y el verificador de Core Web Vitals gratuito muestra el INP de usuarios reales con datos del Chrome UX Report, sin registro. Para más contexto, consulta Core Web Vitals y mastering JavaScript for performance (en inglés). Las pruebas de carga, en cambio, ponen a prueba tus servidores; no revelan el bloqueo del hilo principal en el navegador.
Preguntas frecuentes sobre Web Workers
¿Qué diferencia hay entre un Web Worker y un Service Worker?
Un Web Worker ejecuta JavaScript general en segundo plano para una página. Un service worker se sitúa entre la página y la red y gestiona la caché, el uso sin conexión, las notificaciones push y la sincronización en segundo plano.
¿Puede un Web Worker acceder al DOM?
No. Los workers se ejecutan en su propio contexto, sin DOM. Envían resultados con postMessage y el hilo principal actualiza la página.
¿Hacen los Web Workers que el código se ejecute más rápido?
Por sí solos no. El cálculo tarda más o menos lo mismo, pero ya no bloquea la interfaz. Repartir el trabajo entre varios workers también puede acabarlo antes en dispositivos multinúcleo.
¿Cómo comparten datos los workers?
Mediante paso de mensajes, que copia los datos, transfiriendo objetos como un ArrayBuffer o usando un SharedArrayBuffer cuando se cumplen sus requisitos de seguridad.
¿Necesito un Web Worker en mi aplicación?
Solo si un trabajo intensivo de CPU bloquea el hilo principal. La mayoría de las páginas no lo necesita; las que sí, ganan claramente en capacidad de respuesta.
Términos relacionados
Herramientas LoadFocus relacionadas
Lleva este concepto a la práctica con LoadFocus, la misma plataforma que potencia todo lo que acabas de leer.