La genèse de la Progressive Web App à L’Équipe

Début août 2017, L’Équipe a été l’un des premiers sites français — premier grand média — à lancer une Progressive Web App (PWA). Ce fut l’un de nos chantiers phares de ce début d’année et qui continue à occuper beaucoup notre attention.

Depuis cette sortie, plusieurs confrères qui s’intéressent de près à cette nouveauté — de plus en plus poussée par Google — nous ont contactés pour en savoir un peu plus, aussi bien sur nos objectifs initiaux que sur nos choix techniques ou l’impact sur notre trafic.

C’est ainsi qu’est venue l’idée d’écrire cet article sur la petite histoire de notre PWA, afin de partager notre expérience et on l’espère, vous aider à prendre les bonnes décisions.

Pour lire cet article il vaut mieux avoir quelques notions sur ce qu’est une PWA.

Quels étaient nos objectifs ?

Outre le fait de revoir le design de l’ancienne webapp qui datait un peu, les objectifs de la refonte étaient principalement :

  • de fidéliser les utilisateurs du site mobile qui sont souvent des occasionnels venus des réseaux sociaux ou des moteurs de recherche
    -> seulement 3 pages vues par visite contre 8 pour les applications natives
  • d’améliorer les performances
    -> optimiser le temps de chargement, la rapidité de navigation, la fluidité des animations
  • de proposer un mode offline
    -> pouvoir lire hors connexion un article qui a déjà été chargé auparavant
  • de moderniser l’architecture en se basant sur des APIs dynamiques
    -> utiliser les mêmes APIs que les apps natives et en créer de nouvelles
  • de faire de l’innovation
    ->
    attirer ou retenir les meilleurs développeurs avec du challenge technique

Tous ces objectifs ayant un but commun : faire du site mobile un nouveau levier de croissance pour L’Équipe.

Comment s’est déroulé le projet ?

Phase de réflexion

Le premier défi avant la naissance du projet a été de convaincre en interne. Pour cela, nous avons fait une grande présentation afin d’expliquer ce qu’est une PWA, en quoi nous croyons en l’émergence de cette techno et en sa pertinence pour notre site mobile et comment nous pourrions procéder pour sa mise en place. Une fois cela acté et estimé (5 mois pour couvrir un premier périmètre), nous nous sommes lancés dans la phase de développement.

Phase de développement

Tout d’abord, une équipe très restreinte composée de 2 leads développeurs a été constituée pour défricher le terrain, accompagnée d’un Product Owner pour la partie métier. Après une première cadence (4 sprints de 2 semaines), l’équipe s’est étoffée : 2 développeurs fronts, 2 développeurs back et un PO. Le rôle de scrum master étant tenu par un lead dev.

Phase de tests

Au cours de la 3è cadence, nous étions prêts pour une première mise en production afin de récolter du feedback de nos utilisateurs. La PWA a donc été déployée sur un sous-domaine spécifique en parallèle de l’ancienne webapp. Sur celle-ci nous avons affiché une popin pour proposer à nos utilisateurs de tester la version beta.

Même si cette phase a été relativement courte, elle nous a permis de recueillir un certain nombre de retours utiles à l’aide d’un formulaire Typeform et de corriger le tir sur certains bugs difficilement testables en interne. C’est donc objectivement une réussite.

Cependant, le revers de la médaille c’est qu‘une minorité de mécontents a souvent tendance à s’exprimer davantage que le reste. Le danger est alors de se laisser envahir par le doute devant ces commentaires négatifs (et pas toujours constructifs…).

Phase de production

Après un petit mois de beta et la résolution de tous les problèmes bloquants, la bascule à été réalisée et nous avons dirigé l’ensemble du trafic du site mobile sur la PWA. Pour autant le travail est loin d’être terminé, beaucoup de gabarits de pages restent sur l’ancienne webapp et doivent être peu à peu migrés.

Quel est notre socle technique ?

Le shell

Les recommandations de Google sont de créer un fichier HTML qui fasse office de shell (coquille en anglais) facilement cachable et regroupant toutes les ressources nécessaires au lancement de la PWA hors connexion.

Notre premier réflexe a donc été de vouloir compacter tout le code CSS et JS dans l’index.html. C’est sans doute une solution viable pour un site léger, mais pas lorsque le shell avoisine les 600 Ko, ce qui est notre cas.

En compactant ainsi le JavaScript dans le HTML, impossible de le rendre asynchrone, ce qui impacte l’affichage du premier pixel (First Meaningful Paint). L’utilisateur voyait donc une page blanche plus ou moins longue en fonction de la qualité de son réseau.

De plus notre configuration CDN est paramétrée pour cacher les fichiers JS et CSS pour une longue durée, au contraire du HTML qui a un temps de vie (TTL) très court. Nous avons donc vu notre bande passante exploser.

La solution a été de revoir complètement ce modèle en revenant à une architecture plus classique, mais adaptée : compacter un CSS minimal dans le HTML pour afficher un loader très rapidement et charger le reste du CSS et le JS de manière asynchrone. Nous sommes ainsi arrivés à un chemin critique de rendu bien plus satisfaisant mesuré ci-dessous par l’outil d’audit de performance Lighthouse :

l’affichage de la PWA en slow 3G

Service Worker

Théoriquement, le Service Worker (SW) est la pierre angulaire d’une PWA et gère notamment toute la stratégie de cache de l’app. Dans la pratique, les SW ne sont pour le moment pas supportés sur iOS — mais ça arrive — et c’était difficile pour nous d’expliquer au métier que les utilisateurs d’iOS, Chrome y compris, auraient une expérience moins bonne que sur Android.

Pour contourner cette contrainte et après avoir échangé avec Google qui n’a donné aucune contre-indication, nous avons mis en place un système de cache applicatif basé sur le local storage. Nous n’utilisons le SW que très partiellement pour le Add2Homescreen et la mise en cache du shell, seules fonctionnalités réservées aux utilisateurs Android.

Choix du framework JavaScript

L’utilisation d’un Framework JS n’est pas une obligation pour construire une Progressive Web App. Néanmoins, l’un de nos objectifs étant de partager les APIs avec nos apps natives, il semblait assez évident de se tourner vers une Single Page Application (SPA) et donc un framework JS.

Mais lequel ?

AngularJS (1.x) avait l’avantage d’être bien maîtrisé en interne et donc rapide à mettre en place, tandis que Angular et React, plus modernes et avec la possibilité de faire de l’isomorphisme côté serveur, beaucoup moins.

Essentiellement pour des raisons de timing, nous avons donc opté pour Angular 1.6, avec une architecture en composants qui nous permet de laisser la porte ouverte à une montée de version ultérieure.

Au final, la lecture de cet article nous a plutôt conforté dans notre choix.

Avec un peu plus de recul, la taille du JavaScript étant notre principale contrainte en terme de performance, le choix de ne pas migrer sur Angular 2 (5 désormais) s’est avéré un choix judicieux étant donné son poids colossal.

React ou Vue auraient pu correspondre à notre besoin mais la montée en compétence de l’équipe sur un si gros projet était un frein trop important.

Pre-rendering

Qui dit SPA dit problématiques liées au SEO, un enjeu fort à L’Équipe.

Angular Universal n’étant disponible qu’à partir d’Angular 2, notre alternative pour générer des pages facilement indexable par les moteurs de recherches était de se tourner vers prerender.io.

Avec un coût relativement limité (quelques centaines d’euros par mois pour 800 000 pages indexées) le service remplit sa promesse, même s’il nous oblige à faire quelques ajustements au cas par cas dans notre configuration CDN.

C’est le prix à payer pour ne pas être passé sur un framework plus récent. Nous l’assumons.

Lazyload

Une autre problématique importante, en particulier quand on parle de mobile, c’est la performance.

On a très vite réalisé qu’en ajoutant petit à petit de nouveaux types de pages dans la PWA, la taille de celle-ci n’allait que grimper et que cela aurait impact négatif sur les perfs.

A l’aide du plugin oclazyload, nous avons revu notre approche : désormais, le coeur de l’application est composé uniquement des homes et des pages d’articles et tous les autres types de pages (templates HTML, styles CSS et contrôleurs JS) sont lazyloadés pour ne pas pénaliser le premier chargement.

L’inconvénient de cette technique, c’est que le mode offline ne peut être envisagé que pour les composants embarqués dans le coeur de l’application et plus à l’ensemble du site.

Tests

Chaque feature développée sur la PWA fait l’objet de tests automatisés, lancés à chaque création d’une release.

Nous utilisons la configuration recommandée d’ESlint pour vérifier et corriger automatiquement la syntaxe du code, Karma couplé à Jasmine et ChromeHeadless pour les tests unitaires et Protractor pour les tests fonctionnels effectués sur chaque type de pages.

Et maintenant ?

Avec près de 80% de notre trafic réalisé sur mobile (PWA et apps natives confondues), le développement de la PWA reste au coeur de notre stratégie. Voici deux exemples d’évolutions à venir :

  • La PWA au service des apps natives
    L’arrivée de la PWA a été l’occasion de challenger nos applications natives sur le terrain du offline. Nous avons fait un peu de R&D sur le sujet et travaillé de concert pour mettre au point une solution maison qui consiste à embarquer le shell de la PWA dans les apps et y injecter des flux JSON téléchargés en amont pour rendre un article consultable hors connexion.
    Cette solution est à l’étude mais devrait arriver bientôt.
  • Ajout des notifications
    Nous avions fait le choix de ne pas implémenter les notifications sur la PWA, d’une part car pas encore supporté sur iOS, d’autre part car nous ne savions pas comment éviter d’envoyer les notifications en double à un utilisateur qui aurait installé à la fois notre app native et la PWA. 
    Une nouvelle API disponible depuis Chrome 59, getInstalledRelatedApps, va nous permettre de reconsidérer la question.

Quel bilan peut on faire après 3 mois ?

  • fidéliser les utilisateurs du site mobile
    avant : temps passé/page 37s, temps passé/visite 225s
    après : temps passé/page 40s (+8%), temps passé/visite 234s (+4%)
    -> L’impact de la PWA sur notre trafic n’a pas été aussi important que nous l’espérions, mais cette refonte nous a permis de diminuer le taux de rebond (-1,7%) et d’augmenter les pages vues sur les articles (+10%).
  • améliorer les performances
    tests en slow 3G, avant : DOMContentLoaded 11s, Load 54s, requêtes 192, poids 3.2Mo
    tests en slow 3G, après : DOMContentLoaded <1s, Load 7s, requêtes 77, poids 1.3Mo
    -> toutes les métriques nous confirment que d’un point de vue perfs, la PWA est une réussite, mais cela reste un aspect que nous souhaitons perpétuellement améliorer
  • proposer un mode offline
    -> nous avons réalisé une première étape, il faut maintenant aller plus loin en ajoutant de plus en plus de contenus disponibles hors ligne, tout en veillant à ne pas surcharger la mémoire du téléphone ni la bande passante de l’utilisateur, ce qui rend la chose délicate
  • faire de l’innovation
    -> objectif atteint et même dépassé puisque la PWA nous a permis d’innover au-delà de son périmètre initial (dans les apps natives, le back-office)

Il est peut-être un peu tôt pour tirer des conclusions car il reste beaucoup de travail et d’améliorations à apporter, mais notre sentiment est que la mise en place de la PWA nous a permis de faire un bond en avant technique. Nous la voyons comme une première étape déterminante pour soutenir notre croissance mobile.

En terme de trafic, le site mobile de L’Équipe représente entre 3 et 10 millions de pages vues par jour et au mois d’août 2017 presque 9 millions de visiteurs uniques (Mediametrie).

A lire aussi

Le cas Pinterest
https://medium.com/@addyosmani/a-pinterest-progressive-web-app-performance-case-study-3bd6ed2e6154

La pwa Twitter
https://blog.twitter.com/engineering/en_us/topics/open-source/2017/how-we-built-twitter-lite.html