Pour les besoins d'un projet, j'ai eu à développer une application présentant une expérience hors-ligne très poussée. L'application devait être disponible sur Desktop, mais également sur mobile, pour cette raison le choix d'une Applicative Web Progressive fût fait plutôt qu'une application React native pour profiter de la facilité d'accès d'un site web sur les deux plateformes, ce qui est bien plus complexe avec React native.

Le cahier des charges et les contraintes

Application Gym Santé pour la Fédération Française de Gymnastique

Permettre à des coaches fédérés de pouvoir planifier leurs séances sportives avec les licenciés en puisant dans le catalogue de la fédération. Ces séances doivent être consultables dans les locaux (parfois sans connectivité réseau) de la fédération et l'application facilement installable.

  • Moteur de recherche textuel avec des filtres permettant de trier et de rechercher des contenus tout en étant hors-ligne (soit +/- 1000 documents).
  • Consultation des fiches techniques en faible connectivité ou connectivité inexistante.
  • Saisie de donnée sur Desktop, consultation et modifications mineures en mobile.
  • Impression et export d'une séance au format papier (afin de pouvoir le partager aux usagers).

Challenges techniques

Un moteur de recherche complètement déconnecté

Ce qu'il faut savoir, c'est que la plus grosse partie du contenu de l'application est composée de données froides ce qui permet simplement de mettre en cache cette donnée pour une exploitation future.

Au niveau volumétrie, nous sommes sur du pur JSON, ce qui pour l'ensemble des données nous donne un poids d'approximativement 5 Mo.

La première étape consiste donc à stocker l'intégralité des exercices sportifs dans un index permettant de requêter ces données sans Internet. Ici plusieurs choix possibles, mais après quelques comparaisons, je me suis orienté vers Flexsearch pour sa légèreté et ses grandes performances, notamment dans des services embarqués.

Cet outil permet la recherche textuelle et par filtres divers très rapidement et simplement, couplé à la Context API de React, on peut utiliser le moteur de recherche dans l'ensemble de l'application très simplement.

Préchargement et accès hors-ligne au contenu

N'ayant pas de contraintes spécifiques de versions, je me suis naturellement tourné vers les services-workers et la Cache Storage API, une interface permettant de stocker dans le cache navigateur des requêtes et des réponses HTTP.

Pour faciliter l'intégration, j'ai utilisé Workbox, une librairie de Google qui facilite l'utilisateur des services workers et de la mise en cache, notamment grâce au fait que l'on peut définir des pattern d'URL à mettre en cache à la volée.

Il est également nécessaire de pré-charger certains contenus, ce qui est possible très facilement grâce à la méthode .addAll(urls: string[]) du Cache Storage API. Le navigateur se chargera alors de faire les requêtes nécessaires pour charger les contenus et si cela correspond avec les règles de Workbox, alors les contenus seront bien mis en cache.

Export et impression de PDF sans Internet

Grâce aux deux outils plus haut, on a accès aux contenus, la dernière problématique fût donc de pouvoir générer des PDFs tout en restant dans un contexte de navigateur.

Cette fois beaucoup de chance et une pépite de librairie, j'ai utilisé react-pdf, une surcouche « à la React » de pdfkit qui va permettre de modéliser très simplement son fichier PDF avec des composants React. Le tout sans aucun appel serveur, ne serait-ce que pour les contenus medias qui sont déjà préchargés et mis en cache grâce à Workbox.

Concrètement ça marche comment ?

Au démarrage de l'application, on affiche un écran de chargement qui va s'occuper  de précharger en arrière plan tous les contenus, notamment des exercices. On utilise une règle de cache  Workbox « stale while revalidated » qui permet de servir la donnée en cache et de mettre à jour le cache en arrière plan si c'est possible (réseau).

De cette manière on obtient un chargement plus rapide, contre un léger décalage en cas de mise-à-jour. Dans notre cas cela ne pose pas de problèmes car on est sur de la donnée très froide !

Par soucis de simplicité et contraintes de délais de livraison, sans internet seulement la LECTURE est possible. Toutes les opérations d'écritures déclenchent un message d'erreur indiquant de réitérer lorsque le réseau sera disponible. À savoir que le cas des écritures déconnectées est la problématique la plus grosse des applications offline.

N'hésitez pas à privilégier l'expérience de lecture, faire un produit impeccable et ensuite vous intéresser plus tard à comment vous allez pouvoir gérer les écritures.

En espérant que ces petites resources pourrons vous aider dans vos travaux, je vous dis à bientôt :)