Prácticas recomendadas para programar el registro de tu trabajador de servicio
Los trabajadores de servicio pueden acelerar de manera significativa las visitas repetidas a tu app web, pero debes tomar medidas para asegurarte de que la instalación inicial de un trabajador de servicio no deteriore la experiencia de la primera visita de un usuario.
Por lo general, aplazar el registro del trabajador de servicio hasta que se cargue la página inicial proporcionará la mejor experiencia para los usuarios, en especial para aquellos que usan dispositivos móviles con conexiones de red más lentas.
Plantilla de registro común
Si alguna vez leíste sobre los trabajadores del servicio, es probable que hayas encontrado un texto de referencia similar al siguiente:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js');
}
A veces, esto puede ir acompañado de algunas sentencias console.log()
o código que detectan una actualización de un registro de service worker anterior, como una forma de informar a los usuarios que deben actualizar la página. Pero esas son solo variaciones menores en las pocas líneas de código estándar.
Entonces, ¿hay algún matiz en navigator.serviceWorker.register
? ¿Hay alguna práctica recomendada que deba seguir? No es de extrañar (dado que este artículo no termina aquí), la respuesta a ambas es "¡sí!".
Primera visita de un usuario
Consideremos la primera visita de un usuario a una app web. Aún no hay un trabajador de servicio, y el navegador no tiene forma de saber con anticipación si habrá un trabajador de servicio que se instale más adelante.
Como desarrollador, tu prioridad debe ser asegurarte de que el navegador obtenga rápidamente el conjunto mínimo de recursos críticos necesarios para mostrar una página interactiva. Cualquier elemento que ralentice la recuperación de esas respuestas es el enemigo de una experiencia interactiva rápida.
Ahora imagina que, en el proceso de descargar el código JavaScript o las imágenes que tu página necesita renderizar, el navegador decide iniciar un subproceso o proceso en segundo plano (por motivos de brevedad, supongamos que es un subproceso). Supongamos que no estás usando una computadora de escritorio potente, sino el tipo de teléfono celular de baja potencia que gran parte del mundo considera su dispositivo principal. El inicio de este subproceso adicional agrega contención por el tiempo y la memoria de la CPU que, de otro modo, tu navegador podría dedicar a renderizar una página web interactiva.
Es poco probable que un subproceso en segundo plano inactivo haga una diferencia significativa. Pero ¿qué sucede si ese subproceso no está inactivo, sino que decide que también comenzará a descargar recursos de la red? Cualquier preocupación sobre la contención de la CPU o la memoria debe pasar a un segundo plano en comparación con las preocupaciones sobre el ancho de banda limitado disponible para muchos dispositivos móviles. El ancho de banda es valioso, por lo que no descargues recursos secundarios al mismo tiempo para no perjudicar los recursos críticos.
Todo esto significa que iniciar un nuevo subproceso de trabajador de servicio para descargar y almacenar en caché recursos en segundo plano puede ir en contra de tu objetivo de proporcionar la experiencia interactiva más breve la primera vez que un usuario visita tu sitio.
Mejora el texto estándar
La solución es controlar el inicio del trabajador de servicio eligiendo cuándo llamar a navigator.serviceWorker.register()
. Una regla simple sería retrasar
el registro hasta después de que se active load
event
en window
, de la siguiente manera:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}
Sin embargo, el momento adecuado para iniciar el registro del trabajador de servicio también puede depender de lo que esté haciendo tu app web justo después de que se cargue. Por ejemplo, la app web de Google I/O 2016 incluye una animación breve antes de la transición a la pantalla principal. Nuestro equipo descubrió que iniciar el registro del trabajador de servicio durante la animación podría generar fallas en dispositivos móviles de baja gama. En lugar de ofrecer a los usuarios una experiencia deficiente, retrasamos el registro del trabajador de servicio hasta después de la animación, cuando era más probable que el navegador tuviera algunos segundos inactivos.
Del mismo modo, si tu app web usa un framework que realiza una configuración adicional después de que se cargó la página, busca un evento específico del framework que indique cuándo se realiza ese trabajo.
Visitas posteriores
Hasta ahora, nos hemos enfocado en la experiencia de la primera visita, pero ¿qué impacto tiene el registro retrasado del trabajador de servicio en las visitas repetidas a tu sitio? Si bien esto puede sorprender a algunas personas, no debería haber ningún impacto.
Cuando se registra un service worker, pasa por los eventos del ciclo de vida install
y activate
.
Una vez que se activa un trabajador de servicio, puede controlar eventos fetch
para las visitas posteriores a tu app web. El trabajador de servicio se inicia antes de que se realice la solicitud de cualquier página dentro de su alcance, lo que tiene sentido si lo piensas. Si el trabajador del servicio existente no se estuviera ejecutando antes de visitar una página, no tendría la oportunidad de entregar eventos fetch
para las solicitudes de navegación.
Por lo tanto, una vez que haya un trabajador de servicio activo, no importa cuándo llames a navigator.serviceWorker.register()
ni, de hecho, si lo llamas.
A menos que cambies la URL de la secuencia de comandos del trabajador del servicio, navigator.serviceWorker.register()
es, en realidad, una no operación durante las visitas posteriores. El momento en el que se llama es irrelevante.
Motivos para registrarse con anticipación
¿Hay alguna situación en la que tenga sentido registrar tu service worker lo antes posible? Uno que me viene a la mente es cuando tu trabajador de servicio usa clients.claim()
para tomar el control de la página durante la primera visita y el trabajador de servicio realiza de forma agresiva la caché del tiempo de ejecución dentro de su controlador fetch
. En esa situación, es ventajoso activar el trabajador de servicio lo más rápido posible para intentar propagar sus cachés de tiempo de ejecución con recursos que podrían ser útiles más adelante. Si tu app web pertenece a esta categoría, vale la pena dar un paso atrás para asegurarte de que el controlador install
de tu trabajador de servicio no solicite recursos que compitan por el ancho de banda con las solicitudes de la página principal.
Pruebas
Una excelente manera de simular una primera visita es abrir tu app web en una ventana de incógnito de Chrome y observar el tráfico de red en las Herramientas para desarrolladores de Chrome. Como desarrollador web, es probable que vuelvas a cargar una instancia local de tu app web decenas de veces al día. Sin embargo, cuando vuelves a visitar tu sitio cuando ya hay un trabajador de servicio y cachés completamente propagadas, no obtienes la misma experiencia que un usuario nuevo, y es fácil ignorar un posible problema.
A continuación, se muestra un ejemplo que ilustra la diferencia que podría marcar el tiempo de registro. Ambas capturas de pantalla se tomaron mientras se visitaba una app de ejemplo en modo Incógnito con limitación de red para simular una conexión lenta.

La captura de pantalla anterior refleja el tráfico de red cuando se modificó el ejemplo para realizar el registro del trabajador de servicio lo antes posible. Puedes ver
solicitudes de almacenamiento en caché previo (las entradas con el ícono de engranaje
junto a ellas, que provienen del controlador install
del trabajador del servicio)
intercaladas con solicitudes de los otros recursos necesarios para mostrar la página.

En la captura de pantalla anterior, el registro del trabajador de servicio se retrasó hasta después de que se cargó la página. Puedes ver que las solicitudes de almacenamiento en caché previo no comienzan hasta que se recuperan todos los recursos de la red, lo que elimina cualquier contención por ancho de banda. Además, como algunos de los elementos que almacenamos en caché previamente ya están en la caché HTTP del navegador (los elementos con (from disk cache)
en la columna Tamaño), podemos propagar la caché del trabajador del servicio sin tener que volver a la red.
Obtén puntos adicionales si ejecutas este tipo de prueba desde un dispositivo de gama baja real en una red móvil real. Puedes aprovechar las funciones de depuración remota de Chrome para conectar un teléfono Android a tu computadora de escritorio a través de USB y asegurarte de que las pruebas que ejecutas realmente reflejen la experiencia real de muchos de tus usuarios.
Conclusión
En resumen, asegurarte de que tus usuarios tengan la mejor experiencia en su primera visita debe ser una prioridad. Retrasar el registro del trabajador de servicio hasta después de que se cargue la página durante la visita inicial puede ayudar a garantizarlo. Seguirás obteniendo todos los beneficios de tener un trabajador de servicio para tus visitas repetidas.
Una forma sencilla de garantizar que se retrase el registro inicial del trabajador de servicio hasta que se cargue la primera página es usar lo siguiente:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}