Blog logo

Blog de Rocher

Le guide ultime du stockage frontend : LocalStorage, SessionStorage, Cookies et IndexedDB

Le guide ultime du stockage frontend : LocalStorage, SessionStorage, Cookies et IndexedDB


Publié le
Temps de lecture
Temps de lecture: 16 minutes
Authors

Table des matières

Dans le monde du développement web moderne, le stockage côté navigateur est devenu un élément crucial pour offrir une expérience utilisateur fluide et performante. Mais pourquoi ce besoin de stocker des données directement dans le navigateur est-il si important ?
Imaginez une application web qui, à chaque interaction, doit interroger le serveur pour récupérer ou envoyer des données. Non seulement cela augmente la charge sur le serveur, mais cela ralentit également l'expérience utilisateur coté client(car qui dit requête réseau dit temps de chargement), surtout lorsque la connexion est faible ou instable. C’est ici que le stockage côté navigateur entre en scène: en stockant certaines données localement, vous réduisez les allers-retours entre le client et le serveur, améliorant ainsi la réactivité de l'application et diminuant les coûts liés aux requêtes serveur.
Dans cet article, nous allons explorer en profondeur ces différentes méthodes, en examinant leurs avantages, leurs inconvénients et les cas d'utilisation appropriés. Ce guide vous donnera toutes les clés pour maîtriser le stockage côté frontend et améliorer vos applications web.

Comprendre les bases

Historiquement, le stockage de données côté client a débuté avec les cookies, une technologie qui permettait aux développeurs de conserver des informations simples comme des identifiants de session. Cependant, les cookies avaient leurs limites:

  • espace de stockage très réduit,
  • transmission constante au serveur, et
  • une utilisation souvent détournée pour le suivi publicitaire.

À mesure que les applications web devenaient plus complexes et interactives, la nécessité de solutions de stockage plus flexibles et robustes s'est imposée. Ces dernières offraient une solution pour optimiser les performances, permettre le fonctionnement hors ligne des applications, et offrir une personnalisation accrue pour chaque utilisateur. Aujourd'hui, les développeurs ont à leur disposition plusieurs options pour stocker des données dans le navigateur. Parmi elles, on trouve :

  • LocalStorage: Un espace de stockage persistant pour les données clé-valeur, idéal pour conserver des informations même après la fermeture du navigateur.
  • SessionStorage : Similaire à LocalStorage, mais limité à la session de navigation en cours, avec des données effacées une fois l'onglet ou le navigateur fermé.
  • Cookies : Toujours utiles pour certaines applications, notamment pour gérer les sessions et l'authentification.
  • IndexedDB : Une base de données NoSQL plus avancée, capable de gérer de grandes quantités de données structurées, idéale pour les applications nécessitant un stockage complexe.

Les différents types de stockage côté frontend

Cookies

Un cookie est un petit fichier texte que le navigateur stocke sur l'ordinateur de l'utilisateur à la demande d'un site web. Chaque fois que vous visitez un site, le serveur peut envoyer un ou plusieurs cookies au navigateur, qui les stocke ensuite et les renvoie au serveur lors des visites ultérieures. Les cookies peuvent contenir des informations telles que des identifiants de session, des préférences d'utilisateur, ou des données de suivi. Voici comment le processus fonctionne généralement :

Lorsqu'un utilisateur visite un site web pour la première fois, le serveur peut créer un cookie et l'envoyer au navigateur. Par exemple, un site peut créer un cookie pour sauvegarder la langue de l'utilisateur.

Le navigateur stocke ce cookie sur l'ordinateur de l'utilisateur. Chaque cookie a un nom(unique au sein du domaine qui l'a créé), une valeur(informations que le site souhaite conserver), et des attributs comme une date d'expiration(cet attribut détermine jusqu'à quand le cookie sera valide.) et un domaine(cet attribut définit le domaine pour lequel le cookie est valide.); La liste exhaustive des attributs d'un cookie est disponible sur Mozilla Developers Network.

À chaque visite suivante du même site, le navigateur renvoie automatiquement ce cookie au serveur dans un en-tête HTTP. Cela permet au serveur de reconnaître l'utilisateur et de restaurer l'état de la session ou d'afficher des informations personnalisées.

Il est important de noter que les cookies ont une taille maximale de 4kb et il ne peut en exister plus de 50 par domaine(selon la RFC 6265 - Section 6.1) toutefois cette dernière limite varie selon les navigateurs.

LocalStorage

Le LocalStorage est une technologie de stockage côté navigateur qui fait partie de l'api Web Storage. Cette technologie permet aux développeurs de stocker des paires clé-valeur de manière persistante. Contrairement aux cookies, les données stockées dans LocalStorage ne sont pas envoyées au serveur à chaque requête HTTP, ce qui les rend idéales pour conserver des informations locales sans surcharge inutile pour le serveur. Les données dans LocalStorage sont persistantes, c'est-à-dire qu'elles restent disponibles même après la fermeture du navigateur ou le redémarrage de l'ordinateur, jusqu'à ce que le site ou l'utilisateur les supprime explicitement. Puisque chaque donnée est stockée sous la forme d'une paire clé-valeur, où la clé est une chaîne de caractères unique et la valeur est également une chaîne de caractères. Cela signifie que pour stocker des objets ou des données complexes, il faut généralement convertir ces objets en chaînes de caractères(souvent du JSON) avant de les stocker.

Caractéristiques de LocalStorage

Le LocalStorage offre un espace de stockage limité de 5 à 10 Mo par domaine, ce qui est beaucoup plus grand que les cookies, mais toujours insuffisant pour stocker des fichiers volumineux ou de grandes quantités de données. Il présente plusieurs avantages qui en font un choix populaire pour le stockage de données dans les applications web:

  • Simplicité d'utilisation : L'API de LocalStorage est simple et directe, avec des méthodes comme setItem, getItem, et removeItem pour ajouter, récupérer, et supprimer des données. Cette simplicité le rend accessible même pour les développeurs débutants.

  • Persistant : Contrairement au SessionStorage, les données stockées dans LocalStorage ne sont pas supprimées lorsque l'utilisateur ferme le navigateur. Cela permet de conserver des informations importantes comme les préférences de l'utilisateur, les configurations d'affichage, ou les résultats d'une application et de les restaurer lors de la prochaine visite.

  • Sécurisé et indépendant : Les données sont stockées localement dans le navigateur et ne sont pas envoyées au serveur, ce qui réduit les risques de fuite d'informations sensibles. De plus, chaque domaine a son propre LocalStorage, ce qui empêche l'accès croisé entre les sites.

  • Performances accrues : LocalStorage permet d'accéder rapidement aux données sans avoir à interroger le serveur, ce qui améliore la performance globale de l'application, surtout dans les situations où la latence réseau est un facteur critique.

Exemple pratique: Sauvegarde des préférences utilisateur dans LocalStorage

Pour illustrer l'utilisation de LocalStorage, imaginons que vous développiez une application web où l'utilisateur peut choisir entre un thème clair ou sombre. Vous voulez que le choix de l'utilisateur soit mémorisé afin que la prochaine fois qu'il visite votre site, le même thème soit appliqué.

Voici comment vous pouvez utiliser LocalStorage pour y parvenir :

  1. Stocker le choix du thème :

    Lorsque l'utilisateur choisit un thème, vous pouvez enregistrer cette préférence dans LocalStorage en utilisant la méthode setItem :

    function setThemePreference(theme: string) {
        localStorage.setItem("userTheme", theme);
    }
    

    Par exemple, si le thème sombre est sélectionné, la fonction setThemePreference enregistre la valeur "dark" dans LocalStorage :

    setThemePreference("dark");
    

    Cela crée une entrée dans LocalStorage avec la clé "userTheme" et la valeur "dark".

  2. Récupérer le choix du thème :

    Lors du chargement de la page, vous pouvez vérifier si l'utilisateur a déjà sélectionné un thème et appliquer ce thème automatiquement :

    function applyStoredTheme() {
        const storedTheme = localStorage.getItem("userTheme");
        if (storedTheme) {
            document.body.classList.add(storedTheme);
        } else {
            // Appliquer le thème par défaut si aucun choix n'a été sauvegardé
            document.body.classList.add("light");
        }
    }
    

    Si la valeur "dark" est présente dans LocalStorage, le thème sombre sera appliqué. Sinon, le thème clair (par défaut) sera utilisé.

  3. Supprimer les préférences :

    Si pour une raison quelconque vous souhaitez réinitialiser ou supprimer le choix de l'utilisateur, vous pouvez simplement supprimer l'entrée dans LocalStorage :

    function clearThemePreference() {
        localStorage.removeItem("userTheme");
    }
    

    Cela réinitialise l'application pour qu'elle utilise le thème par défaut lors de la prochaine visite.
    LocalStorage est une solution simple et efficace pour stocker des données persistantes dans le navigateur. Grâce à sa facilité d'utilisation et à sa capacité à conserver des données même après la fermeture du navigateur, il est idéal pour des cas d'utilisation comme la mémorisation des préférences utilisateur, le stockage des paramètres d'application, ou la gestion de sessions prolongées. Toutefois, il est important de l'utiliser de manière judicieuse, notamment en tenant compte des limites de capacité et des implications potentielles sur la sécurité des données.

SessionStorage

SessionStorage est une technologie de stockage côté navigateur qui, comme son nom l'indique, est limitée à la durée d'une session de navigation. Cela signifie que les données stockées dans SessionStorage ne sont disponibles que pendant la durée de vie de la session. Une fois que l'utilisateur ferme l'onglet ou la fenêtre du navigateur, toutes les données stockées sont automatiquement supprimées. Le SessionStorage est similaire à LocalStorage en ce sens qu'il stocke des paires clé-valeur.

Avantages de SessionStorage

  • Durée de vie limitée : Contrairement à LocalStorage, où les données peuvent persister indéfiniment (ou jusqu'à ce qu'elles soient supprimées manuellement), SessionStorage garantit que les données sont supprimées dès que la session de l'utilisateur se termine. Cela en fait un excellent choix pour les informations sensibles à court terme, comme les étapes intermédiaires dans un processus de transaction.

  • Isolation des sessions : SessionStorage est isolé par onglet ou fenêtre. Cela signifie que chaque nouvel onglet ouvert à partir de la même page web aura son propre espace de stockage, indépendant des autres onglets. Cela est utile dans les applications où plusieurs onglets doivent gérer des états distincts sans interférer les uns avec les autres.

  • Simplicité d'utilisation : Tout comme LocalStorage, SessionStorage utilise une interface simple et intuitive pour stocker, récupérer et supprimer des données. Les méthodes setItem, getItem, et removeItem sont également utilisées pour manipuler les données.

Limites de SessionStorage

  • Durée de vie limitée à une session : La caractéristique principale de SessionStorage est aussi sa limitation majeure. Si l'utilisateur ferme l'onglet ou la fenêtre du navigateur, toutes les données sont perdues. Si la persistance des données après une session est nécessaire, LocalStorage ou d'autres solutions doivent être utilisées.

  • Capacité limitée : SessionStorage a une capacité de stockage généralement limitée à environ 5 Mo(En réalité, cette limite dépend du navigateur utilisé), similaire à LocalStorage. Cette capacité est souvent plus que suffisante pour la plupart des cas d'utilisation, mais elle ne convient pas aux données volumineuses ou persistantes.

Exemple pratique : Stockage des étapes d'une session d'achat

Prenons un exemple d'application e-commerce où vous avez un processus d'achat en plusieurs étapes (panier, livraison, paiement). Vous pouvez utiliser SessionStorage pour stocker temporairement les informations liées à l'utilisateur pour chaque étape, afin d'assurer une navigation fluide sans que les données ne persistent au-delà de cette session.

  1. Stocker les informations : Supposons que l'utilisateur ait sélectionné des articles dans son panier. Vous pouvez stocker cette sélection dans SessionStorage pour conserver l'état du panier pendant la session.

    function saveCartItems(cart) {
        sessionStorage.setItem("cartItems", JSON.stringify(cart));
    }
    
  2. Récupérer les informations : Lorsqu'un utilisateur revient sur la page de paiement ou de confirmation, vous pouvez récupérer les articles stockés dans la session :

    function getCartItems() {
        const cartItems = sessionStorage.getItem("cartItems");
        return cartItems ? JSON.parse(cartItems) : [];
    }
    
  3. Effacement des informations : Lorsque l'utilisateur complète la transaction ou quitte la page de paiement, vous pouvez supprimer les données stockées pour libérer l'espace :

    function clearCart() {
        sessionStorage.removeItem("cartItems");
    }
    

Dans cet exemple, SessionStorage permet de stocker des informations de manière temporaire pour améliorer l'expérience utilisateur sans avoir à se soucier de la persistance des données après la session.

IndexedDB

Qu'est-ce qu'IndexedDB ?

IndexedDB est une API de stockage côté navigateur qui permet de stocker des quantités significatives de données structurées. Contrairement à LocalStorage et SessionStorage, qui sont limités à des paires clé-valeur simples et à une capacité de stockage relativement petite (environ 5 Mo), IndexedDB offre une base de données NoSQL puissante directement dans le navigateur. Cela permet de stocker et de gérer des données complexes, comme des objets JavaScript, des fichiers Blob, et bien plus encore.

  • Base de données NoSQL : IndexedDB est une base de données orientée documents qui utilise des objets JavaScript pour stocker et récupérer des données. Elle est asynchrone et utilise des transactions pour garantir l'intégrité des données.

  • Grande capacité de stockage : IndexedDB offre une capacité de stockage beaucoup plus importante que LocalStorage ou SessionStorage. La limite de stockage dépend du navigateur et de l'espace disque disponible, mais elle peut atteindre plusieurs centaines de mégaoctets, voire plusieurs gigaoctets.

  • Supporte les index : Comme son nom l'indique, IndexedDB permet de créer des index sur vos données, ce qui améliore considérablement les performances lors de la recherche et du tri.

Avantages d'IndexedDB

  • Stockage de grandes quantités de données : IndexedDB est conçu pour gérer des applications qui nécessitent de stocker beaucoup de données côté client, comme des applications de gestion, des éditeurs de documents, ou des applications de médias.

  • Données structurées et complexes : Vous pouvez stocker des objets JavaScript complets, ce qui facilite la gestion des données structurées sans avoir à les sérialiser manuellement.

  • Performances élevées : IndexedDB est optimisé pour les opérations de lecture et d'écriture rapides, même avec de grandes quantités de données.

  • Fonctionnement hors ligne : En stockant les données localement, les applications peuvent continuer à fonctionner même sans connexion Internet, améliorant ainsi l'expérience utilisateur.

  • Transactions sécurisées : IndexedDB utilise des transactions pour garantir que les opérations de lecture et d'écriture sont atomiques, cohérentes, isolées et durables (ACID), ce qui renforce la fiabilité des applications.

Exemple pratique : Création d'une application de gestion de tâches avec IndexedDB

Imaginons que vous souhaitiez créer une application de gestion de tâches (to-do list) qui fonctionne même hors ligne et qui peut stocker un grand nombre de tâches avec des détails complexes.

1. Ouvrir une base de données

Pour utiliser IndexedDB, vous devez d'abord ouvrir une connexion à une base de données, en spécifiant son nom et sa version :

let db;
const request = indexedDB.open("ToDoListDB", 1);

request.onupgradeneeded = function(event) {
  db = event.target.result;
  const objectStore = db.createObjectStore("tasks", { keyPath: "id", autoIncrement: true });
  objectStore.createIndex("title", "title", { unique: false });
  objectStore.createIndex("dueDate", "dueDate", { unique: false });
};

request.onsuccess = function(event) {
  db = event.target.result;
  // Maintenant, vous pouvez commencer à interagir avec la base de données
};

request.onerror = function(event) {
  console.error("Erreur lors de l'ouverture de la base de données :", event.target.errorCode);
};

Dans cet exemple :

  • indexedDB.open : Ouvre une connexion à la base de données nommée "ToDoListDB" à la version 1.
  • onupgradeneeded : Événement déclenché lors de la création initiale ou de la mise à jour de la base de données. C'est ici que vous définissez la structure de votre base de données.
  • createObjectStore : Crée un magasin d'objets nommé "tasks" avec une clé primaire "id" qui s'auto-incrémente.
  • createIndex : Crée des index sur les champs "title" et "dueDate" pour faciliter les requêtes.

2. Ajouter des tâches à la base de données

Pour ajouter une nouvelle tâche, vous utilisez une transaction en mode lecture-écriture :

function addTask(task) {
  const transaction = db.transaction(["tasks"], "readwrite");
  const objectStore = transaction.objectStore("tasks");
  const request = objectStore.add(task);

  request.onsuccess = function() {
    console.log("Tâche ajoutée avec succès !");
  };

  request.onerror = function(event) {
    console.error("Erreur lors de l'ajout de la tâche :", event.target.errorCode);
  };
}

// Exemple d'ajout d'une tâche
addTask({
  title: "Acheter du lait",
  description: "Acheter du lait au supermarché",
  dueDate: new Date("2023-12-31"),
  completed: false
});

3. Récupérer et afficher les tâches

Pour récupérer toutes les tâches et les afficher :

function getAllTasks() {
  const transaction = db.transaction(["tasks"], "readonly");
  const objectStore = transaction.objectStore("tasks");
  const request = objectStore.getAll();

  request.onsuccess = function(event) {
    const tasks = event.target.result;
    tasks.forEach(task => {
      console.log(`Tâche : ${task.title}, À faire avant le : ${task.dueDate}`);
    });
  };

  request.onerror = function(event) {
    console.error("Erreur lors de la récupération des tâches :", event.target.errorCode);
  };
}

// Appel de la fonction pour récupérer et afficher les tâches
getAllTasks();

4. Mettre à jour une tâche

Pour mettre à jour une tâche existante :

function updateTask(id, updatedData) {
  const transaction = db.transaction(["tasks"], "readwrite");
  const objectStore = transaction.objectStore("tasks");
  const request = objectStore.get(id);

  request.onsuccess = function(event) {
    const task = event.target.result;
    Object.assign(task, updatedData);

    const updateRequest = objectStore.put(task);
    updateRequest.onsuccess = function() {
      console.log("Tâche mise à jour avec succès !");
    };
  };

  request.onerror = function(event) {
    console.error("Erreur lors de la récupération de la tâche :", event.target.errorCode);
  };
}

// Exemple de mise à jour
updateTask(1, { completed: true });

5. Supprimer une tâche

Pour supprimer une tâche :

function deleteTask(id) {
  const transaction = db.transaction(["tasks"], "readwrite");
  const objectStore = transaction.objectStore("tasks");
  const request = objectStore.delete(id);

  request.onsuccess = function() {
    console.log("Tâche supprimée avec succès !");
  };

  request.onerror = function(event) {
    console.error("Erreur lors de la suppression de la tâche :", event.target.errorCode);
  };
}

// Exemple de suppression
deleteTask(1);

Quand utiliser IndexedDB ?

IndexedDB est particulièrement utile pour :

  • Applications web complexes : Comme les éditeurs de texte, les jeux, ou les applications de dessin qui nécessitent de stocker beaucoup de données côté client.

  • Fonctionnalités hors ligne : Pour les applications qui doivent fonctionner sans connexion Internet, en stockant les données localement et en les synchronisant avec le serveur lorsque la connexion est rétablie.

  • Performance optimisée : Lorsque vous devez accéder rapidement à de grandes quantités de données sans surcharger le serveur ou la bande passante réseau.

Considérations et bonnes pratiques

  • Asynchronisme : IndexedDB est entièrement asynchrone. Toutes les opérations se font via des événements ou des promesses, ce qui peut ajouter de la complexité dans la gestion du code.

  • Compatibilité des navigateurs : Bien que largement supporté par les navigateurs modernes, il est important de vérifier la compatibilité pour les navigateurs plus anciens ou spécifiques.

  • Sécurité : Comme pour tout stockage côté client, évitez de stocker des informations sensibles non chiffrées dans IndexedDB.

  • Quota de stockage : Même si IndexedDB offre une grande capacité de stockage, les navigateurs peuvent demander la permission à l'utilisateur lorsque de grandes quantités de données sont stockées. Il est donc judicieux de gérer efficacement l'espace utilisé.

En conclusion, le stockage côté frontend offre une variété d'options, chacune adaptée à des cas d'utilisation spécifiques. Que vous ayez besoin de stocker des données de session temporaires avec SessionStorage, des préférences persistantes avec LocalStorage, ou des données structurées et volumineuses avec IndexedDB, ces outils vous permettent de créer des applications web plus rapides, plus réactives et plus personnalisées. Toutefois, il est essentiel de prendre en compte les aspects de sécurité et de performance lors du choix de la solution la plus appropriée. En maîtrisant ces différentes technologies, vous pourrez concevoir des applications frontend robustes tout en offrant une meilleure expérience utilisateur.