Ce que l'équipe du Bulletin a appris sur les travailleurs de service lors du développement d'une PWA.
Esta es la primera de una serie de publicaciones de Blog sobre las lecciones que aprendió el equipo de Google Bulletin al crear una PWA externa. En estas publicaciones compartiremos algunos de los desafíos que enfrentamos, los enfoques que tomamos para superarlos y consejos generales para evitar trampas. Esta no es de ninguna manera una descripción general completa de las PWA. El objectif es compartir los aprendizajes de la experiencia de nuestro equipo.
Pour ce premier article, nous aborderons d'abord un peu d'informations générales, puis nous plongerons dans tout ce que nous avons appris sur les travailleurs des services.
Le bulletin a été fermé en 2019 en raison d'un manque d'ajustement produit / marché. Nous avons encore beaucoup appris sur les PWA en cours de route!
Antécédents
Bulletin était en développement actif de mi-2017 à mi-2019.
Pourquoi nous avons choisi de construire une PWA
Avant de plonger dans le processus de développement, examinons pourquoi la création d'une PWA était une option intéressante pour ce projet:
- Capacité à itérer rapidement. Particulièrement précieux car le Bulletin serait testé sur plusieurs marchés.
- Base de code unique. Nuestros usuarios se dividieron aproximadamente en partes iguales entre Android e iOS. Una PWA significaba que podíamos crear una única aplicación la toile que funcionara en ambas plataformas. Esto aumentó la velocidad y el impacto del equipo.
- Actualizado rápidamente e independientemente del comportamiento del Nom d'utilisateur. Les PWA peuvent être automatiquement mis à jour, ce qui réduit le nombre de clients obsolètes dans la nature. Nous avons pu conduire des changements majeurs au backend avec un temps de migration très court pour les clients.
- Il s'intègre facilement à vos propres applications et à des applications tierces. Tales integraciones eran un requisito para la aplicación. Con una PWA, a menudo significaba simplemente abrir una URL.
- Le frottement de l'installation d'une application a été supprimé.
Notre cadre
Pour Bulletin, nous utilisons Polymère, mais n'importe quel framework moderne et bien pris en charge fera l'affaire.
Ce que nous avons appris sur les travailleurs des services
Vous ne pouvez pas avoir une PWA sans une travailleur de service. Los trabajadores de servicios le brindan mucho poder, como estrategias avanzadas de almacenamiento en cache, capacidades fuera de línea, sincronización en segundo plano, etc. Si bien los trabajadores de servicios agregan algo de complejidad, descubrimos que sus beneficios superan la complejidad adicional.
Générez-le si vous le pouvez
Évitez d'écrire un script de service worker à la main. L'écriture manuelle des services worker nécessite de gérer manuellement les ressources mises en cache et de réécrire la logique commune à la plupart des bibliothèques de service worker, telles que Boîte de travail.
Cela dit, en raison de notre pile technologique interne, nous n'avons pas pu utiliser une bibliothèque pour générer et gérer notre technicien de service. Nos apprentissages ci-dessous refléteront parfois cela. Accédez à Problèmes pour les techniciens de service non générés pour en savoir plus.
Toutes les bibliothèques ne sont pas compatibles avec les techniciens de service
Certaines bibliothèques JS émettent des hypothèses qui ne fonctionnent pas comme prévu lorsqu'elles sont exécutées par un service worker. Par exemple, en supposant la fenêtre
ou document
están disponibles, o usando una API no disponible para los trabajadores del servicio (XMLHttpRequest
, stockage local, etc.). Assurez-vous que les bibliothèques critiques dont vous avez besoin pour votre application sont prises en charge par les techniciens de maintenance. Pour cette PWA particulière, nous voulions utiliser
gapi.js para la autenticación, pero no pudieron hacerlo porque no admitía a los trabajadores del servicio. Los autores de bibliotecas también deben reducir o eliminar suposiciones innecesarias sobre el contexto de JavaScript siempre que être posible para respaldar los casos de uso de trabajadores de servicios, como evitar API incompatibles con trabajadores de servicios y evitar el estado global.
Évitez d'accéder à IndexedDB pendant l'initialisation
Ne lis pas IndexedDB lors de l'initialisation de votre script de service worker, ou vous pouvez vous retrouver dans cette situation indésirable:
- L'utilisateur dispose d'une application Web avec IndexedDB (IDB) version N
- Une nouvelle application Web est incluse avec la version N + 1 de la BID
- L'utilisateur visite PWA, ce qui déclenche le téléchargement d'un nouveau service worker
- Le nouveau service worker lit dans la base de données IDB avant de s'enregistrer
installer
gestionnaire d'événements, activation d'un cycle de mise à jour BID pour passer de N à N + 1 - Dado que el usuario tiene un client antiguo con la versión N, el proceso de actualización del trabajador del servicio se bloquea ya que las conexiones activas todavía están abiertas a la versión anterior de la base de datos
- Le technicien de service se bloque et n'installe jamais
Dans notre cas, le cache est invalidé lors de l'installation du service worker, donc si le service worker n'a jamais été installé, les utilisateurs n'ont jamais reçu l'application mise à jour.
Rendez-le difficile
Aunque los scripts de los trabajadores de servicios se ejecutan en segundo plano, también se pueden finalizar en cualquier momento, incluso cuando se encuentran en medio de operaciones de E / S (red, IDB, etc.). Cualquier proceso de larga duración debería poder reanudarse en cualquier momento.
En el caso de un proceso de sincronización que cargó archivos grandes al serveur y se guardó en el BID, nuestra solución para las cargas parciales interrumpidas fue aprovechar el sistema reanudable de nuestra biblioteca de carga interna, guardando la URL de carga reanudable en el BID antes de cargar y usar esa URL para reanudar una carga si no se completó la primera vez. Además, antes de cualquier operación de E / S de larga duración, el estado se guardaba en IDB para indicar en qué parte del proceso estábamos para cada registro.
Ne dépendez pas de l'état mondial
Étant donné que les techniciens de service existent dans un contexte différent, de nombreux symboles que vous pourriez espérer exister ne sont pas présents. Une grande partie de notre code fonctionnait sur les deux la fenêtre
contexte, ainsi qu'un contexte de service worker (tel que l'enregistrement, les indicateurs, la synchronisation, etc.). Le code doit être défensif sur les services que vous utilisez, tels que le stockage local ou les cookies. Vous pouvez utiliser
globalThis
pour faire référence à l'objet global d'une manière qui fonctionne dans tous les contextes. Utilisez également les données stockées dans les variables globales avec parcimonie, car il n'y a aucune garantie lorsque le script se terminera et que l'état sera expulsé.
Développement local
La mise en cache des ressources localement est un élément important des agents de service. Cependant, pendant le développement, c'est le opposé que vous ne le souhaitez, surtout lorsque les mises à jour sont effectuées paresseusement. Vous souhaitez toujours installer le serveur de travail afin de pouvoir déboguer les problèmes avec celui-ci ou travailler avec d'autres API telles que la synchronisation en arrière-plan ou les notifications. Dans Chrome, vous pouvez y parvenir via Chrome DevTools en activant le Bypass pour le réseau case à cocherDemander panneau> Travailleurs de service panneau) en plus d'activer le Désactiver le cache case à cocher dans le Rapporter panel para deshabilitar también la memoria caché. Para cubrir más navigateurs, optamos por una solución diferente al incluir una marca para deshabilitar el almacenamiento en caché en nuestro trabajador de servicio, que está habilitado de forma predeterminada en las compilaciones de desarrolladores. Esto asegura que los desarrolladores siempre obtengan sus cambios más recientes sin problemas de almacenamiento en caché. Es importante incluir el Cache-Control: pas de cache
encabezado también para evitar que el le navigateur almacene en caché cualquier activo.
Phare
Phare proporciona una serie de herramientas de depuración útiles para las PWA. Escanea un sitio y genera informes que cubren PWA, rendimiento, accesibilidad, SEO y otras mejores prácticas.
Nous recommandons exécution de Lighthouse en intégration continue pour vous faire savoir si vous ne répondez à aucun des critères pour être un PWA. Cela nous est arrivé une fois, alors que le technicien de service n'installait pas et que nous n'avions pas remarqué une augmentation de la production auparavant. Le fait d'avoir Lighthouse dans notre CI l'aurait empêché.
Adoptez la livraison continue
Étant donné que les techniciens de service peuvent se mettre à jour automatiquement, les utilisateurs n'ont pas la possibilité de limiter les mises à jour. Cela réduit considérablement le nombre de clients obsolètes dans la nature. Lorsque l'utilisateur a ouvert notre application, le technicien de service a servi l'ancien client tout en téléchargeant paresseusement le nouveau client. Une fois le nouveau client téléchargé, il demandera à l'utilisateur d'actualiser la page pour accéder aux nouvelles fonctionnalités. Même si l'utilisateur ignorait cette demande, la prochaine fois qu'il actualiserait la page, il recevrait la nouvelle version du client. En conséquence, il est assez difficile pour un utilisateur de rejeter les mises à jour de la même manière qu'il le peut pour les applications natives.
Nous avons pu conduire des changements majeurs au backend avec un temps de migration très court pour les clients. Nous donnons généralement aux utilisateurs un mois pour passer à des clients plus récents avant d'apporter des modifications majeures. Étant donné que l'application fonctionnerait alors qu'elle était obsolète, il était possible que des clients plus anciens existent dans la nature si l'utilisateur n'avait pas ouvert l'application pendant une longue période. Sur iOS, les techniciens de service sont
expulsé après quelques semaines
por lo que este caso no sucede. Para Android, este problema podría mitigarse si no se publica mientras está obsoleto o si el Contenu caduca manualmente después de algunas semanas. En la práctica, nunca encontramos problemas con clientes obsoletos. Cuán estricto quiere ser un equipo dado aquí depende de su caso de uso específico, pero las PWA brindan una flexibilidad significativamente mayor que las aplicaciones nativas.
Obtenir les valeurs de cookie dans un service worker
Parfois, il est nécessaire d'accéder aux valeurs des cookies dans le contexte d'un technicien de service. Dans notre cas, nous devions accéder aux valeurs des cookies pour générer un jeton afin d'authentifier les requêtes API d'origine. Dans un service worker, des API synchrones comme document.cookies
no están disponibles. Siempre puede enviar un mensaje a los clientes activos (con ventana) desde el trabajador del servicio para solicitar los valores de las cookies, aunque es posible que el trabajador del servicio se ejecute en segundo plano sin ningún cliente con ventana disponible, como durante una sincronización en segundo plano. Para solucionar esto, creamos un punto final en nuestro servidor l'extrémité avant que simplemente devolvía el valor de la cookie al cliente. El trabajador del servicio realizó una solicitud de red a este punto final y leyó la respuesta para obtener los valores de las cookies.
Avec le lancement du
API du magasin de cookies, cette solution de contournement ne devrait plus être nécessaire pour les navigateurs qui la prennent en charge, car elle fournit un accès asynchrone aux cookies du navigateur et peut être utilisée directement par le technicien de service.
Pièges pour les travailleurs des services non générés
Assurez-vous que le script du service worker change si vous modifiez des fichiers statiques mis en cache
Un modèle PWA courant permet à un technicien de service d'installer tous les fichiers d'application statiques pendant leur
installer
phase, qui permet aux clients d'accéder directement au cache de l'API de mise en cache pour toutes les visites suivantes. Les services worker ne sont installés que lorsque le navigateur détecte que le script de service worker a changé d'une manière ou d'une autre, nous avons donc dû nous assurer que le fichier de script de service worker a changé d'une manière ou d'une autre lors de la modification d'un fichier mis en cache. Nous l'avons fait manuellement en incorporant un hachage de l'ensemble des fichiers de ressources statiques dans notre script de service worker, de sorte que chaque version produisait un fichier JavaScript de service worker différent. Les bibliothèques de service worker telles que
Boîte de travail Automatisez ce processus pour vous.
Examen de l'unité
Les API de service worker fonctionnent en ajoutant des écouteurs d'événements à l'objet global. Par exemple:
soi.addEventListener('fetch', (evt) => evt.respondWith(aller chercher('/foo')));
Esto puede ser difícil de probar porque necesita simular el disparador del un événement, el objeto del evento, esperar el répondre avec ()
callback, puis attendez la promesse, avant d'affirmer enfin le résultat. Un moyen plus simple de structurer cela consiste à déléguer l'intégralité de l'implémentation à un autre fichier, ce qui est plus facile à tester.
importer fetchHandler desde './fetch_handler.js';
soi.addEventListener('fetch', (evt) => evt.respondWith(fetchHandler(evt)));
En raison des difficultés de test unitaire d'un script de service worker, nous avons gardé le script de service worker de base aussi basique que possible, en divisant la plupart de l'implémentation en d'autres modules. Étant donné que ces fichiers n'étaient que des modules JS standard, ils pourraient être plus facilement testés unitairement avec des bibliothèques de test standard.
Restez à l'écoute pour les parties 2 et 3
Dans les parties 2 et 3 de cette série, nous parlerons de la gestion des médias et des problèmes spécifiques à iOS. Si vous souhaitez nous demander plus d'informations sur la création d'une PWA sur Google, visitez nos profils d'auteurs pour savoir comment nous contacter: