Registro de service worker

Prácticas recomendadas para saber cuándo registrar un service worker.

Los service workers pueden acelerar considerablemente las visitas repetidas a tu app web, pero debes seguir ciertos pasos para que la instalación inicial de un service worker no degrade la experiencia de la primera visita del usuario.

Por lo general, esperar hasta que se cargue la página inicial para el registro del trabajador de servicio proporcionará la mejor experiencia para los usuarios, especialmente para aquellos que usan dispositivos móviles con conexiones de red más lentas.

Modelo convencional de registros

Si ya estás familiarizado con los service workers, es probable que ya conozcas texto similar a este:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
}

Es probable que esté acompañado de algunas instrucciones console.log() o de código que detecte una actualización de un registro de service worker anterior, para que los usuarios sepan que hay que actualizar la página. Pero son solo pequeñas variaciones de las pocas líneas del código estándar.

Entonces, ¿hay algún matiz en navigator.serviceWorker.register? ¿Existen prácticas recomendadas que deba seguir? No debería sorprender (dado que el artículo no termina aquí) que la respuesta a ambas preguntas sea "¡sí!".

Primera visita de un usuario

Pensemos en la primera visita del usuario a una app web. Todavía no hay ningún service worker, y el navegador no tiene forma de saber con anticipación si se instalará uno.

Como programador, tu prioridad debe ser que el navegador obtenga rápidamente el conjunto mínimo de recursos críticos que sean necesarios para mostrar una página interactiva. El elemento que demore este proceso será enemigo de cualquier experiencia fluida e interactiva.

Ahora supongamos que durante el proceso de descarga de JavaScript o de las imágenes que tu página necesita renderizar, el navegador decide iniciar un proceso o subproceso en segundo plano (para no explayarnos tanto, supongamos que es un subproceso). Supongamos que tu máquina no es muy potente; es el tipo de teléfono celular con poca potencia que la mayoría de las personas usan como dispositivo principal. La ejecución de este subproceso adicional agrega cargas al tiempo de CPU y a la memoria, recursos que tu navegador usaría para representar una página web interactiva.

Es probable que los subprocesos en segundo plano que estén inactivos no marquen mucha diferencia. Pero ¿qué ocurre si el subproceso no está inactivo y, en su lugar, decide que también comenzará a descargar recursos de la red? Cualquier preocupación sobre cargas en el CPU o la memoria será secundaria en comparación con los problemas de ancho de banda limitado que tienen muchos dispositivos móviles. El ancho de banda es un bien preciado, así que no descargues recursos secundarios al mismo tiempo, ya que debilitarás los recursos críticos.

Lo que quiero decir es que si ejecutas un nuevo subproceso de service worker para descargar y almacenar en caché recursos en segundo plano, es posible que vaya en contra de tu objetivo: proporcionar la experiencia más rápida e interactiva durante la primera visita del usuario a tu sitio.

Mejora el modelo

La solución es controlar el inicio del service worker. Para eso, se debe elegir cuándo realizar una llamada a navigator.serviceWorker.register(). Una regla simple es demorar 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');
    });
}

Pero el momento adecuado para iniciar el registro del service worker también puede depender de lo que haga tu app web inmediatamente después de que se carga. Por ejemplo, la app web de Google I/O 2016 muestra una pequeña animación antes de pasar a la pantalla principal. Nuestro equipo descubrió que si se ejecuta el registro del service worker durante la animación, los dispositivos móviles de gama baja pueden tener problemas. En lugar de brindar una mala experiencia a los usuarios, demoramos el registro del service worker hasta después de la animación, cuando era más probable que el navegador tuviera unos segundos libres.

Del mismo modo, si tu app web usa un framework que realiza configuraciones adicionales después de cargar la página, busca un evento específico del framework que indique cuándo termina ese trabajo.

Visitas posteriores

Hasta ahora, hablamos de la experiencia durante la primera visita. ¿Pero cómo afecta la demora del registro del service worker a visitas posteriores de tu sitio? Si bien esto podría 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 service worker, puede controlar los eventos fetch para cualquier visita posterior a tu app web. El service worker se inicia antes de que se realice la solicitud a cualquier página de su alcance, lo que tiene sentido si lo piensas. Si el service worker existente no estuviese funcionando antes de visitar una página, no podría realizar los eventos fetch para las solicitudes de navegación.

Por lo tanto, si hay un service worker activo, no importa cuándo llames a navigator.serviceWorker.register() o, de hecho, si lo llamas o no. A menos que cambies la URL de la secuencia de comandos del service worker, navigator.serviceWorker.register() es, en realidad, una no operación en las visitas posteriores. El momento de la llamada es irrelevante.

Razones para realizar el registro más temprano

¿En qué escenarios tiene sentido registrar el service worker apenas sea posible? Uno que se me viene a la mente es cuando tu service worker usa clients.claim() para tomar el control de la página durante la primera visita y el service worker realiza de forma agresiva el almacenamiento en caché en tiempo de ejecución dentro de su controlador fetch. En esa situación, hay una ventaja de activar el service worker lo antes 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 tomarse un tiempo para asegurarse de que el controlador install de tu servicio de trabajador no solicite recursos que compitan por el ancho de banda con las solicitudes de la página principal.

Cómo realizar pruebas

Una buena forma de simular una primera visita es abrir la app web en una ventana de incógnito de Chrome y observar el tráfico de red en DevTools de Chrome. Como desarrollador web, probablemente cargas una instancia local de tu app web decenas y decenas de veces al día. Sin embargo, si visitas nuevamente tu sitio cuando ya hay un service worker y las cachés están completas, no obtienes la misma experiencia que un usuario nuevo y es fácil pasar por alto cualquier problema potencial.

Aquí se describe un ejemplo con la diferencia que puede marcar el momento del registro: Ambas capturas de pantalla se toman cuando se visita una app de ejemplo en modo incógnito con limitación de red para simular una conexión lenta.

Tráfico de red con registro anticipado.

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

Tráfico de red con registro tardío.

En la captura de pantalla anterior, se demoró el registro del service worker hasta después de cargar la página. Puedes ver que las solicitudes de almacenamiento previo en caché no comienzan hasta que se obtienen todos los recursos de la red. De esta forma, se elimina cualquier problema de ancho de banda. Además, dado que algunos de los elementos que almacenamos previamente en caché ya se encuentran en la caché HTTP del navegador (los elementos con (from disk cache) en la columna Size), podemos completar la caché del service worker sin tener que volver a la red.

Ganas puntos adicionales si realizas este tipo de prueba en un dispositivo móvil de gama baja y una red móvil real. Puedes aprovechar las funciones de depuración remota de Chrome para conectar un teléfono Android a tu máquina de escritorio a través de USB y asegurarte de que las pruebas que realizas reflejen la experiencia real de muchos de tus usuarios.

Conclusión

En resumen, asegurarte de que los usuarios tengan la mejor experiencia durante la primera visita debe ser una prioridad. Si demoras el registro del service worker hasta que se cargue la página durante la primera visita, es posible que te sea más fácil cumplir con esta prioridad. Seguirás disfrutando de todos los beneficios de tener un service worker para las visitas posteriores.

A continuación, se muestra una forma simple y directa que puedes usar para asegurarte de que el registro inicial del service worker se realice después de la carga de la primera página:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}