Aller au contenu
Perrine HonoréPerrine Honoré · Blog
MobilePar Perrine Honoré · · 7 min de lecture

Offline-first : concevoir une app mobile qui marche sans réseau

Métro, zone blanche, wifi capricieux : le réseau n'est jamais fiable. Cache local, synchronisation, gestion des conflits : le guide offline-first pour votre app.

Illustration d'une application mobile fonctionnant hors connexion avec une file de synchronisation vers le cloud
En bref

L'offline-first consiste à faire lire et écrire l'application d'abord dans une base locale sur le téléphone, la synchronisation avec le serveur se faisant en arrière-plan. Pour toute application utilisée en mobilité : techniciens terrain, commerciaux, livraison, inventaire, santé, ce n'est pas un luxe : c'est ce qui décide entre adoption et abandon.

Vos utilisateurs ne vivent pas dans vos conditions de test. Ils sont dans le métro, dans un parking souterrain, sur un chantier en zone blanche, dans un TGV où la 4G apparaît et disparaît toutes les trente secondes. Et quand votre app leur répond par un spinner infini ou un écran d'erreur, ils ne se disent pas « le réseau est mauvais » : ils se disent « cette app est nulle ».

Pour toute application utilisée en mobilité : techniciens terrain, commerciaux, livraison, inventaire, santé, le mode hors ligne n'est pas un luxe : c'est ce qui décide si l'app est adoptée ou abandonnée.

L'idée clé de l'offline-first : l'application lit et écrit d'abord dans une base de données locale, sur le téléphone. Le réseau ne sert qu'à synchroniser en arrière-plan. Résultat : l'app est instantanée et fonctionne toujours : le réseau devient une optimisation, pas une dépendance.

Pourquoi « on gérera le offline plus tard » ne marche pas

C'est la demande d'évolution la plus coûteuse que je rencontre en reprise de projet. Une app construite en mode « chaque écran appelle l'API » (online-first) a le réseau câblé dans toute son architecture : chaque vue, chaque bouton suppose une réponse serveur immédiate. Ajouter le hors-ligne après coup revient à réécrire la couche de données entière, souvent 30 à 50 % de l'app.

À l'inverse, décider dès la conception que la source de vérité locale est une base embarquée coûte peu : c'est un choix d'architecture, pas une fonctionnalité de plus. C'est exactement le genre d'arbitrage à trancher pendant le cadrage du projet, pas au sprint 12.

Côté lecture : les stratégies de cache

Pour afficher des données, trois stratégies principales, du plus simple au plus robuste :

  • Réseau d'abord, cache en secours : on tente l'API, et en cas d'échec on affiche la dernière version connue. Simple, mais l'app reste lente quand le réseau est mauvais (il faut attendre le timeout).
  • Cache d'abord, rafraîchissement en arrière-plan (stale-while-revalidate) : on affiche immédiatement les données locales, puis on les met à jour silencieusement si le réseau répond. C'est le meilleur rapport simplicité/expérience pour les données consultatives.
  • Réplication complète : une copie locale des données de l'utilisateur est maintenue en permanence par un moteur de synchronisation. C'est l'approche offline-first au sens strict, la plus confortable à l'usage, la plus exigeante à construire.

Côté écriture : la file d'attente de synchronisation

Le vrai sujet n'est pas la lecture, c'est l'écriture. Quand un technicien valide une intervention sans réseau, que se passe-t-il ? La réponse robuste tient en trois mécanismes :

  1. Écriture locale immédiate : la modification est enregistrée dans la base embarquée et l'interface la reflète instantanément (interface dite « optimiste »).
  2. File d'attente persistante : chaque modification est empilée dans une file stockée sur l'appareil, elle survit au redémarrage de l'app et du téléphone.
  3. Rejeu au retour du réseau : la file est envoyée au serveur dans l'ordre, avec reprise sur erreur. Point crucial : les opérations doivent être idempotentes, envoyer deux fois la même opération (à cause d'une coupure au mauvais moment) ne doit pas créer de doublon. Un identifiant unique généré côté client suffit généralement.

La résolution de conflits : le sujet qui fâche

Deux personnes modifient la même fiche pendant que l'une est hors ligne : qui gagne ? Il n'y a pas de réponse universelle, mais des politiques à choisir par type de donnée :

  • Le dernier qui écrit gagne (last-write-wins) : simple et suffisant pour la majorité des champs. Assumez-le explicitement plutôt que de le subir.
  • Fusion par champ : deux modifications sur des champs différents de la même fiche ne sont pas un conflit, fusionnez-les au lieu d'écraser la fiche entière.
  • Arbitrage humain : pour les données critiques (un compte rendu signé, un montant), on garde les deux versions et on demande à l'utilisateur. Rare, mais rassurant.
  • Structures auto-fusionnantes (CRDT) : la solution des outils collaboratifs temps réel. Puissant mais complexe, n'y allez que si la co-édition est le cœur de votre produit.

Mon conseil : réduisez le problème à la conception. Des opérations plutôt que des écrasements (« ajouter 1 au stock » plutôt que « stock = 42 »), des entités possédées par un seul utilisateur quand c'est possible, et 90 % des conflits disparaissent.

Les outils : ne réinventez pas le moteur de sync

OutilCe que c'estQuand le choisir
SQLite (+ Drizzle/Room/GRDB)Base locale embarquée, standard absoluToujours, c'est la fondation ; sync à construire soi-même
WatermelonDBBase réactive pour React Native, pensée offline-firstApp React Native avec beaucoup de données et d'écrans réactifs
PowerSyncMoteur de synchronisation managé entre Postgres et SQLite localBackend Postgres existant, besoin de réplication robuste sans la développer
Realm / Firestore offlineBases avec sync intégrée à leur écosystèmeSi vous acceptez l'adhérence forte à l'écosystème en question

Écrire son propre moteur de synchronisation complet est un projet dans le projet, comptez plusieurs semaines rien que pour les cas limites. Pour une file d'attente simple d'écritures, en revanche, le sur-mesure reste raisonnable.

L'UX du hors-ligne : dire la vérité, sans dramatiser

  • Affichez un indicateur discret de l'état de synchronisation (« 3 éléments en attente »), pas une bannière rouge anxiogène.
  • Ne bloquez jamais une action qui peut être mise en file. Le bouton « Valider » doit fonctionner hors ligne.
  • Distinguez visuellement l'état local (enregistré sur l'appareil) de l'état synchronisé pour les données critiques.
  • Testez en conditions réelles : mode avion, mais aussi, plus vicieux, le mauvais réseau (une barre de 3G), qui révèle les timeouts mal réglés. Les outils de développement permettent de simuler ces conditions, et le monitoring en production vous dira ce que vivent vraiment vos utilisateurs.

Tester le offline-first : au-delà du mode avion

Le mode avion est un test binaire : réseau présent ou absent. Il ne révèle qu'une fraction des vrais problèmes. Les incidents que je vois le plus souvent en production viennent des situations intermédiaires :

  • Le réseau qui coupe en plein envoi : la requête part, la connexion tombe avant la réponse. Le client ne sait pas si l'opération a réussi côté serveur : sans identifiant idempotent, il la renvoie et crée un doublon.
  • Le réseau lent plutôt qu'absent : une 2G résiduelle en zone rurale peut être pire qu'une coupure franche, car l'app attend un timeout long avant de basculer en mode dégradé. Fixez des délais d'attente courts et explicites plutôt que de laisser le système d'exploitation décider.
  • Le changement de réseau en cours d'usage : passage du wifi à la 4G en sortant d'un bâtiment, avec changement d'adresse IP. Une synchronisation mal conçue peut dupliquer ou perdre des opérations à cet instant précis.

Les outils de simulation réseau des environnements de développement mobile permettent de rejouer ces trois scénarios avant la mise en production : c'est un budget de test modeste comparé au coût d'un incident chez un client qui découvre des données dupliquées sur le terrain.

Le stockage local : ce qu'il faut prévoir dès le départ

Une base embarquée n'est pas un espace infini. Quelques arbitrages à trancher tôt, pendant la conception plutôt qu'en urgence après un premier incident :

  • Politique de rétention : combien de temps garde-t-on les données localement avant de les purger ? Un historique complet sur des années finit par ralentir l'app et gonfler l'espace occupé sur le téléphone.
  • Chiffrement au repos : un téléphone professionnel perdu ou volé expose sa base locale si elle n'est pas chiffrée. Pour des données sensibles (santé, RH, finance), c'est un prérequis, pas une option, à intégrer dans votre check-list de sécurité mobile.
  • Taille de la synchronisation initiale : un nouvel utilisateur qui doit télécharger des années de données avant de pouvoir travailler abandonnera. Prévoyez une synchronisation par tranches ou par pertinence (les dossiers actifs d'abord).
Une app mobile qui exige du réseau en permanence est une app web déguisée, et vos utilisateurs sur le terrain le découvrent toujours au pire moment.

Votre app doit tenir sans réseau ?

Le mode hors ligne se joue à la conception : c'est là que je peux vous faire gagner des mois. Réservez un appel découverte pour cadrer votre projet d'app terrain. À lire ensuite : PWA ou application native ? et combien de temps pour développer une app mobile.

Une question avant l'appel ?

Je réponds personnellement sous 24 h ouvrées.

Le bouton ouvre votre messagerie avec le message prêt. Si rien ne s'ouvre, écrivez directement à perrine.honore@gmail.com.