Chrome 153 abre la caja negra de los Web Workers: LoAF llega al hilo secundario
Chrome 153 (estable el 8 de septiembre de 2026) extiende la API de Long Animation Frames a los Web Workers: las tareas largas que bloquean el event loop de un worker ahora son medibles por dentro. Te contamos cómo instrumentar pipelines de video en WebCodecs, el caso real de nuestro portal médico y cuándo el worker —y no el hilo principal— es tu verdadero cuello de botella.
Chrome 153 abre la caja negra de los Web Workers: LoAF llega al hilo secundario
Cada vez que movemos trabajo pesado a un Web Worker —procesar video con WebCodecs, transformar imágenes, parsear archivos grandes— protegemos el INP del hilo principal, pero creamos una nueva caja negra: nadie ve lo que pasa dentro del worker. Chrome 153, estable el 8 de septiembre de 2026, cierra ese hueco: la API de Long Animation Frames se extiende a los Web Workers y, con los marcadores de JS Self-Profiling (en origin trial), por fin es posible medir dónde se atora un pipeline off-main-thread.
Durante dos años, el consejo de rendimiento fue una letanía: "saca el trabajo pesado del hilo principal". En Mintec lo aplicamos hasta el extremo: nuestro portal médico de video genera miniaturas con WebCodecs dentro de un worker dedicado, y WordPress 7.1 ya procesa medios en el cliente dentro de un Web Worker. El problema: una vez que el código vive en un worker, las herramientas clásicas se quedan ciegas. Lighthouse no ve workers. LoAF solo reportaba el hilo principal. El INP decía "todo bien" mientras el worker se ahogaba silenciosamente procesando un HEVC 4K de 2 GB.
Chrome 153 cambia eso. Es la primera versión del nuevo ciclo de lanzamiento quincenal, y llega con dos piezas de telemetría que no existían: LoAF dentro de Web Workers y los JS Self-Profiling Markers en origin trial. Si construyes pipelines de media en el navegador, esto importa más que cualquier feature visual.
Por qué el worker se volvió un agujero negro (y nadie lo notó)
El patrón dominante en sitios con mucho media: subes un archivo, un worker lo decodifica con VideoDecoder, extrae frames, los redimensiona en un OffscreenCanvas y los codifica como WebP mientras el hilo principal sigue respondiendo clics. El usuario ve un spinner de "procesando" que no refleja nada real: "será el servidor", "será el CDN", "será la librería".
Ninguna métrica decía la verdad: la verdad vivía en el event loop del worker. El INP se calcula sobre el hilo principal: si el worker se bloquea 30 segundos, la página sigue rindiendo "bien" en el laboratorio, porque nadie mide la experiencia de subir un video. La API de Long Animation Frames, estable desde Chrome 123 y ya en todos los motores, captura frames >50ms y los atribuye a scripts concretos — pero solo del hilo principal. En nuestro artículo sobre INP en sitios con mucho media documentamos cómo LoAF reveló que un reproductor de terceros ejecutaba detección de ancho de banda en cada interacción; lo que no pudimos ver fue el trabajo ya delegado a los workers.
Qué trae Chrome 153 exactamente
Según las notas de release de Chrome 153:
- LoAF en Web Workers dedicados. Una tarea larga que bloquea el event loop de un worker se reporta como una entrada
long-animation-frame, observable dentro del worker conPerformanceObserver, con la atribución por script de siempre. Hasta ahora LoAF estaba anclado a los frames de renderizado del hilo principal; un bloqueo en el worker era invisible por diseño. - JS Self-Profiling Markers (origin trial). La JS Self-Profiling API ahora etiqueta cada muestra con el tipo de actividad del navegador:
script,gc,style,layout,paintuother. Atribuye el tiempo que antes aparecía como "huecos" entre stacks: distingue una recolección de basura de un recálculo de estilos.
La instrumentación es directa:
// dentro del worker
if (PerformanceObserver.supportedEntryTypes?.includes('long-animation-frame')) {
const obs = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
postMessage({
type: 'loaf-worker',
duration: entry.duration,
blocking: entry.blockingDuration,
scripts: entry.scripts?.map((s) => ({ name: s.name, duration: s.duration })),
});
}
});
obs.observe({ type: 'long-animation-frame', buffered: true });
}
Tres líneas que cierran la caja negra: el worker se reporta y el hilo principal agrega esos datos a la telemetría.
El mapa completo de qué herramienta ve qué
| Herramienta | Hilo principal | Web Worker | Qué te dice | Disponibilidad |
|---|---|---|---|---|
| INP (CrUX/CWVs) | ✅ | ❌ | Qué tan lenta es la interacción del usuario | Todos los motores |
| LoAF (clásico) | ✅ | ❌ | Qué scripts bloquean los frames >50ms | Chrome 123+, Safari, Firefox |
| LoAF en workers | ✅ | ✅ | Tareas >50ms dentro del event loop del worker, con scripts | Chrome 153 (sep 2026) |
| JS Self-Profiling Markers | ✅ | ✅ | A qué se atribuye el tiempo: script, gc, layout, paint… | Origin trial en 153 |
| Lighthouse | ✅ | ❌ | Auditoría de laboratorio en carga | Todas las herramientas |
La fila que importa es la tercera: por fin podemos responder "¿el worker es el cuello de botella?" con datos, no con corazonadas.
El caso real: el stall invisible de nuestro portal médico
Cuando migramos la generación de miniaturas de ffmpeg en servidores (45–120s por video, instancias EC2 c5.4xlarge que colapsaban con HEVC 4K de móviles) a WebCodecs en el navegador —1.2–3.5 segundos con costo de cómputo cero—, el frontend quedó impecable y el INP intacto. Apareció un síntoma nuevo: los editores reportaban que "a veces el procesamiento tarda muchísimo y a veces es instantáneo".
Medimos tiempo de subida, tamaño de archivo y console.time dentro del worker: nada explicaba los picos de 10–30 segundos. Sospechábamos del encode de WebP compitiendo con la decodificación de HEVC en el mismo worker, pero no había forma de probarlo: el event loop del worker era una caja negra.
Con LoAF en workers hubiéramos visto los long-animation-frame de 8–12 segundos atribuidos al encode concurrente, y el fix —separar decodificación y encode en dos workers y limitar a una operación activa— habría sido evidente en horas, no en semanas. Hoy esa instrumentación es parte de nuestro estándar en pipelines de video con WebCodecs: medir dentro del worker es tan importante como en el hilo principal.
Marco de triage para workers lentos
Cuando un pipeline off-main-thread se comporta mal, usamos esta secuencia: (1) confirma que el worker recibe trabajo —si postMessage no llega, el problema es upstream—; (2) instrumenta LoAF en el worker: long-animation-frame > 200ms = el worker es el cuello de botella, y scripts[].duration nombra la función; (3) revisa las marcas del origin trial: gc = asignación excesiva, layout/paint = tocando el DOM mal desde OffscreenCanvas, script = CPU pura; (4) aplica el remedio de la tabla.
| Síntoma en el worker | Causa típica | Remedio |
|---|---|---|
LoAF largos y continuos, script dominante | Cómputo secuencial pesado (encode compite con decode) | Separar en dos workers o mantener una operación activa |
Picos de gc cada pocos frames | Asignación excesiva (frames temporales sin .close()) | Frame pooling y close() explícito — el error clásico de WebCodecs |
| Bloqueos correlacionados con subidas grandes | Contención de red + CPU en el mismo worker | Priorizar decode, diferir encode, o usar otro worker |
| Sin LoAF en el worker pero mala UX de "procesando" | El problema no es el worker: es la UI que no refleja progreso | Progreso por postMessage con eventos reales del pipeline |
Un patrón recurrente: el VideoFrame olvidado (sin .close()) genera una montaña de GC invisible. Ahora se ve —y se ve en el worker.
Dónde debe vivir cada tarea, en 2026
La extensión de LoAF no cambia la decisión de arquitectura: la hace más informada.
| Tarea | Hilo principal | Worker dedicado | Servidor |
|---|---|---|---|
| Miniatura/preview de video conocido (H.264) | ❌ | ✅ WebCodecs (HW) — subsegundo, cero infra | Solo legado |
| Conversión de formato (mp4 → webm) | ❌ | ⚠️ WebCodecs limitado a códecs nativos | ✅ ffmpeg |
| Archivos raros o corruptos | ❌ | ❌ | ✅ ffmpeg con -movflags +faststart |
| Edición en tiempo real (timeline) | ⚠️ solo UI | ✅ decode/encode | Export final |
| Lotes de archivos legados | ❌ | ❌ | ✅ por costo y rareza de formatos |
La regla sigue siendo la de nuestras estrategias de media pesado en Astro: produce una vez, sirve muchas. Ahora, cuando el worker es la opción, al menos sabemos lo que hace.
Nuestra opinión clara
Chrome 153 es la release de rendimiento más importante del año para sitios con media, y casi nadie lo está comentando. Los releases quincenales —empezando por este— acelerarán estas mejoras; los equipos que siguen probando "las últimas dos versiones de cada navegador" perderán el rastro. La medición de INP con LoAF y el navigator.cpuPerformance para servir video según el dispositivo fueron el primer acto; medir el worker es el segundo.
Dos advertencias honestas. Primero, esto es Chrome-only hoy: detecta con supportedEntryTypes y mantén marcas propias en Safari/Firefox. Segundo, la telemetría no sustituye el diseño: si puedes evitar el trabajo pesado en el cliente (AVIF ya servido, posters), hazlo. Pero cuando el cliente tiene que procesar —subidas de video, avatares, generación en tiempo real—, deja de adivinar: mide dentro del worker.
Fuentes: Chrome Platform Status, release notes de Chrome 153 (LoAF en Web Workers; JS Self-Profiling Markers en origin trial); CSS Wizardry, "Web-Perf Wednesday 007 — Chrome Makes Busy Workers Measurable" (septiembre 2026); MDN, Long Animation Frames API. Datos de producción: proyecto de portal médico de video de Mintec (2026).
Preguntas Frecuentes
¿Qué es LoAF en Web Workers?
Chrome 153 extiende la API Long Animation Frames (LoAF) a los Web Workers dedicados: una tarea que bloquea el event loop de un worker más de 50ms se reporta como entrada long-animation-frame observable dentro del worker con PerformanceObserver, incluida la atribución por script.
¿Cómo mido tareas largas dentro de un Web Worker?
Dentro del worker, detecta la capacidad con PerformanceObserver.supportedEntryTypes y observa el tipo 'long-animation-frame': cada entrada trae duration, blockingDuration y scripts. Reenvía los datos al hilo principal con postMessage para unirlos al resto de la telemetría.
¿LoAF en Web Workers funciona en todos los navegadores?
Hoy es exclusivo de Chrome 153 (septiembre de 2026); el resto de motores mantiene LoAF solo en el hilo principal. Lo recomendable: detección de capacidades con marcas propias como relleno para las operaciones críticas.



