Découvrez les bonnes pratiques pour synchroniser l'état de l'application entre IndexedDB et les bibliothèques de gestion de l'état populaires.
Lorsqu'un utilisateur charge un site Web ou une application pour la première fois, la création de l'état initial de l'application utilisé pour afficher l'UI nécessite souvent un certain travail. Par exemple, l'application doit parfois authentifier l'utilisateur côté client, puis effectuer plusieurs requêtes API avant de disposer de toutes les données nécessaires pour afficher la page.
Stocker l'état de l'application dans IndexedDB peut être un excellent moyen d'accélérer le temps de chargement pour les visites répétées. L'application peut ensuite se synchroniser avec n'importe quel service d'API en arrière-plan et mettre à jour l'UI avec de nouvelles données de manière paresseuse, en utilisant une stratégie obsolète pendant la validation.
Toutefois, lorsque vous utilisez IndexedDB, de nombreux points importants à prendre en compte peuvent ne pas être immédiatement évidents pour les développeurs qui ne connaissent pas encore les API. Ce document répond à des questions courantes et aborde certains des points les plus importants à garder à l'esprit lors de la persistance de l'état de l'application dans IndexedDB.
Prévoir le comportement de votre application
La plupart des complexités liées à IndexedDB proviennent du fait qu'il existe de nombreux facteurs sur lesquels vous (le développeur) n'avez aucun contrôle. Cette section explore de nombreux problèmes que vous devez garder à l'esprit lorsque vous travaillez avec IndexedDB.
Les écritures dans l'espace de stockage peuvent échouer
Des erreurs peuvent se produire lors de l'écriture dans IndexedDB pour diverses raisons, et dans certains cas, ces raisons échappent à votre contrôle en tant que développeur. Par exemple, certains navigateurs n'autorisent pas l'écriture dans IndexedDB en mode navigation privée. Il est également possible qu'un utilisateur se trouve sur un appareil dont l'espace disque est presque saturé, et que le navigateur ne lui permette plus de stocker quoi que ce soit.
C'est pourquoi il est essentiel d'implémenter toujours une gestion des erreurs appropriée dans votre code IndexedDB. Cela signifie également qu'il est généralement judicieux de conserver l'état de l'application en mémoire (en plus de le stocker), afin que l'UI ne se bloque pas lorsqu'elle s'exécute en mode navigation privée ou lorsque l'espace de stockage n'est pas disponible (même si certaines des autres fonctionnalités de l'application qui nécessitent un espace de stockage ne fonctionneront pas).
Les données stockées ont peut-être été modifiées ou supprimées par l'utilisateur.
Contrairement aux bases de données côté serveur, où vous pouvez limiter l'accès non autorisé, les bases de données côté client sont accessibles aux extensions de navigateur et aux outils de développement, et peuvent être effacées par l'utilisateur.
Il est rare que les utilisateurs modifient les données stockées localement, mais il est courant qu'ils les effacent. Il est important que votre application puisse gérer ces deux cas sans erreur.
Les données stockées sont peut-être obsolètes
Comme dans la section précédente, même si l'utilisateur n'a pas modifié les données lui-même, il est également possible que les données qu'il a stockées aient été écrites par une version antérieure de votre code, qui peut contenir des bugs.
IndexedDB est compatible avec les versions de schéma et la mise à niveau à l'aide de sa méthode IDBOpenDBRequest.onupgradeneeded()
. Toutefois, vous devez toujours écrire votre code de mise à niveau de manière à pouvoir gérer l'utilisateur provenant d'une version précédente (y compris une version avec un bug).
Les tests unitaires peuvent être très utiles dans ce cas, car il est souvent impossible de tester manuellement tous les chemins et cas de mise à niveau possibles.
Maintenir la performance de votre application
L'une des principales caractéristiques d'IndexedDB est son API asynchrone, mais ne vous laissez pas tromper en pensant que vous n'avez pas à vous soucier des performances lorsque vous l'utilisez. Dans certains cas, une utilisation incorrecte peut toujours bloquer le thread principal, ce qui peut entraîner une absence de réponse.
En règle générale, les lectures et les écritures dans IndexedDB ne doivent pas être plus importantes que nécessaire pour les données auxquelles on accède.
Bien que IndexedDB permette de stocker de grands objets imbriqués en tant qu'enregistrement unique (et que cette pratique soit très pratique du point de vue du développeur), elle doit être évitée. En effet, lorsque IndexedDB stocke un objet, il doit d'abord créer un clone structuré de cet objet, et le processus de clonage structuré se produit sur le thread principal. Plus l'objet est volumineux, plus le temps de blocage est long.
Cela présente certains défis lorsque vous planifiez la persistance de l'état de l'application dans IndexedDB, car la plupart des bibliothèques de gestion d'état populaires (comme Redux) fonctionnent en gérant l'ensemble de votre arborescence d'état en tant qu'objet JavaScript unique.
Bien que la gestion de l'état de cette manière présente de nombreux avantages, et que le stockage de l'ensemble de l'arborescence d'état en tant qu'enregistrement unique dans IndexedDB puisse être tentant et pratique, le faire après chaque modification (même si le débit est limité/déboulé) entraînera un blocage inutile du thread principal, ce qui augmentera la probabilité d'erreurs d'écriture et, dans certains cas, entraînera même le plantage de l'onglet du navigateur ou son incapacité à répondre.
Au lieu de stocker l'ensemble de l'arborescence des états dans un seul enregistrement, vous devez la diviser en enregistrements individuels et ne mettre à jour que les enregistrements qui changent réellement.
Comme pour la plupart des bonnes pratiques, il ne s'agit pas d'une règle de tout ou rien. Dans les cas où il n'est pas possible de diviser un objet d'état et d'écrire simplement le lot de modifications minimal, il est préférable de diviser les données en sous-arbres et de n'écrire que ceux-ci plutôt que d'écrire toujours l'ensemble de l'arbre d'état. Les petites améliorations sont meilleures que l'absence d'améliorations.
Enfin, vous devez toujours mesurer l'impact sur les performances du code que vous écrivez. Bien qu'il soit vrai que les petites écritures dans IndexedDB soient plus efficaces que les grandes écritures, cela n'a d'importance que si les écritures dans IndexedDB que votre application effectue entraînent réellement des tâches longues qui bloquent le thread principal et dégradent l'expérience utilisateur. Il est important de mesurer pour comprendre ce que vous optimisez.
Conclusions
Les développeurs peuvent utiliser des mécanismes de stockage client tels que IndexedDB pour améliorer l'expérience utilisateur de leur application en conservant l'état au fil des sessions, mais aussi en réduisant le temps de chargement de l'état initial lors des visites répétées.
Bien que l'utilisation correcte d'IndexedDB puisse considérablement améliorer l'expérience utilisateur, une utilisation incorrecte ou un échec de la gestion des erreurs peut entraîner des applications défectueuses et des utilisateurs mécontents.
Étant donné que le stockage client implique de nombreux facteurs hors de votre contrôle, il est essentiel que votre code soit bien testé et gère correctement les erreurs, même celles qui peuvent sembler initialement peu probables.