GraphQL - Mise en cache

La mise en cache est le processus de stockage des données dans une zone de stockage temporaire appelée cache. Lorsque vous revenez sur une page que vous avez récemment visitée, le navigateur peut récupérer ces fichiers à partir du cache plutôt que du serveur d'origine. Cela économise votre temps et votre réseau du fardeau du trafic supplémentaire.

Les applications clientes interagissant avec GraphQL sont responsables de la mise en cache des données à leur extrémité. Un modèle possible pour cela est de réserver un champ, comme id, pour être un identifiant globalement unique.

Cache InMemory

InMemoryCache est un magasin de données normalisé couramment utilisé dans les applications clientes GraphQL sans utilisation d'une autre bibliothèque comme Redux.

L'exemple de code pour utiliser InMemoryCache avec ApolloClient est donné ci-dessous -

import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const cache = new InMemoryCache();

const client = new ApolloClient({
   link: new HttpLink(),
   cache
});

Le constructeur InMemoryCache prend un objet de configuration facultatif avec des propriétés pour personnaliser votre cache.

N ° Sr. Paramètre et description
1

addTypename

Un booléen pour déterminer s'il faut ajouter __typename au document (par défaut: true)

2

dataIdFromObject

Une fonction qui prend un objet de données et renvoie un identifiant unique à utiliser lors de la normalisation des données dans le magasin

3

fragmentMatcher

Par défaut, InMemoryCache utilise un sélecteur de fragments heuristique

4

cacheRedirects

Une carte de fonctions pour rediriger une requête vers une autre entrée du cache avant qu'une requête n'ait lieu.

Illustration

Nous allons créer une application d'une seule page dans ReactJS avec deux onglets - un pour l'onglet d'accueil et un autre pour les étudiants. L'onglet étudiants chargera les données depuis une API serveur GraphQL. L'application interrogera les données des étudiants lorsque l'utilisateur navigue de l'onglet d'accueil à l'onglet étudiants. Les données résultantes seront mises en cache par l'application.

Nous interrogerons également l'heure du serveur en utilisant getTimepour vérifier si la page est mise en cache. Si des données sont renvoyées depuis le cache, la page affichera l'heure de la toute première requête envoyée au serveur. Si les données sont le résultat d'une nouvelle demande adressée au serveur, elles afficheront toujours la dernière heure du serveur.

Configuration du serveur

Voici les étapes de configuration du serveur -

Étape 1 - Téléchargez et installez les dépendances requises pour le projet

Créer un dossier cache-server-app. Changez votre répertoire en cache-server-app depuis le terminal. Suivez les étapes 3 à 5 expliquées dans le chapitre Configuration de l'environnement.

Étape 2 - Créer un schéma

Ajouter schema.graphql fichier dans le dossier du projet cache-server-app et ajoutez le code suivant -

type Query {
   students:[Student]
   getTime:String
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   fullName:String
}

Étape 3 - Ajouter des résolveurs

Créez un fichier resolvers.js dans le dossier du projet et ajoutez le code suivant -

const db = require('./db')

const Query = {
      students:() => db.students.list(),
      getTime:() => {
      const today = new Date();
      var h = today.getHours();
      var m = today.getMinutes();
      var s = today.getSeconds();
      return `${h}:${m}:${s}`;
   }
}
module.exports = {Query}

Étape 4 - Exécutez l'application

Créez un fichier server.js. Reportez-vous à l'étape 8 du chapitre Configuration de l'environnement. Exécutez la commande npm start dans le terminal. Le serveur sera opérationnel sur le port 9000. Ici, nous utiliserons GraphiQL comme client pour tester l'application.

Ouvrez le navigateur et entrez l'URL http://localhost:9000/graphiql. Tapez la requête suivante dans l'éditeur -

{
   getTime
   students {
      id
      firstName
   }
}

L'exemple de réponse montre les noms des étudiants et l'heure du serveur.

{
   "data": {
      "getTime": "22:18:42",
      "students": [
         {
            "id": "S1001",
            "firstName": "Mohtashim"
         },
         {
            "id": "S1002",
            "firstName": "Kannan"
         },
         {
            "id": "S1003",
            "firstName": "Kiran"
         }
      ]
   }
}

Configuration du client ReactJS

Ouvrez un nouveau terminal pour le client. Le terminal serveur doit continuer à fonctionner avant d'exécuter l'application client. L'application React fonctionnera sur le port numéro 3000 et l'application serveur sur le port numéro 9000.

Étape 1 - Créer une application React

Dans le terminal client, tapez la commande suivante -

npx create-react-app hello-world-client

Cela installera tout le nécessaire pour une application de réaction typique. lenpx utility et create-react-apptools crée un projet avec le nom hello-world-client. Une fois l'installation terminée, ouvrez le projet dans VSCode.

Installez les modules de routeur pour réagir en utilisant la commande suivante - npm install react-router-dom.

Étape 2 - Démarrez hello-world-client

Modifiez le chemin du dossier actuel dans le terminal en hello-world-client. Tapez npm start pour lancer le projet. Cela exécutera un serveur de développement sur le port 3000 et ouvrira automatiquement le navigateur et chargera la page d'index.

Ceci est montré dans la capture d'écran ci-dessous -

Étape 3 - Installer les bibliothèques clientes Apollo

Pour installer un client Apollo, ouvrez un nouveau terminal et soyez dans le chemin du dossier du projet actuel. Tapez la commande suivante -

npm install apollo-boost graphql

Cela téléchargera les bibliothèques graphql côté client ainsi que le package Apollo Boost. Nous pouvons vérifier cela en tapant npm view dépendances apollo-boost. Cela aura de nombreuses dépendances comme indiqué ci-dessous -

{ 
   'apollo-cache': '^1.1.15',
   'apollo-cache-inmemory': '^1.2.8',
   'apollo-client': '^2.4.0',
   'apollo-link': '^1.0.6',
   'apollo-link-error': '^1.0.3',
   'apollo-link-http': '^1.3.1',
   'apollo-link-state': '^0.4.0',
   'graphql-tag': '^2.4.2' 
}

Nous pouvons clairement voir que la bibliothèque apollo-client est installée.

Étape 4 - Modifier le composant d'application dans le fichier index.js

Pour une application de réaction simple, il vous suffit de conserver le index.js dans src dossier et index.htmldans un dossier public; tous les autres fichiers générés automatiquement peuvent être supprimés.

La structure des répertoires est donnée ci-dessous -

hello-world-client /
   -->node_modules
   -->public
      index.html
   -->src
      index.js
      students.js
   -->package.json

Ajoutez un fichier supplémentaire student.js qui contiendra le composant Elèves. Les détails de l'étudiant sont récupérés via le composant étudiant. Dans le composant App, nous utilisons un HashRouter.

Voici le index.js dans l'application React -

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {HashRouter, Route, Link} from 'react-router-dom'

//components
import Students from './students'
class App extends Component {
   render() {
      return(
         <div><h1>Home !!</h1>
         <h2>Welcome to React Application !! </h2>
         </div>
      )
   }
}

function getTime() {
   var d = new Date();
   return d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()
}

const routes = <HashRouter>
   <div>
      <h4>Time from react app:{getTime()}</h4>
      <header>
         <h1>  <Link to="/">Home</Link> 
         <Link to = "/students">Students</Link>  </h1>
      </header>
      <Route exact path = "/students" component = {Students}></Route>
      <Route exact path = "/" component = {App}></Route>
   </div>
</HashRouter>

ReactDOM.render(routes, document.querySelector("#root"))

Étape 5 - Modifier les étudiants du composant dans Students.js

Dans le composant Élèves, nous utiliserons les deux approches suivantes pour charger des données -

  • Fetch API (loadStudents_noCache) - Cela déclenchera une nouvelle demande à chaque fois que vous cliquerez sur l'onglet étudiant.

  • Apollo Client (loadWithApolloclient) - Cela récupérera les données du cache.

Ajouter une fonction loadWithApolloclientquelles requêtes pour les étudiants et l'heure du serveur. Cette fonction activera la mise en cache. Ici, nous utilisons une fonction gql pour analyser la requête.

async loadWithApolloclient() {
   const query = gql`{
      getTime
      students {
         id
         firstName
      }
   }`;

   const {data} = await  client.query({query})
   return data;
}

le Fetch APIest une interface simple pour récupérer des ressources. Fetch facilite la création de requêtes Web et la gestion des réponses qu'avec l'ancien XMLHttpRequest. La méthode suivante montre le chargement des données directement à l'aide de Fetch api -

async  loadStudents_noCache() {
      const response = await fetch('http://localhost:9000/graphql', {
      method:'POST',
      headers:{'content-type':'application/json'},
      body:JSON.stringify({query:`{
         getTime
         students {
            id
            firstName
         }
      }`})
   })

   const rsponseBody = await response.json();
   return rsponseBody.data;
}

Dans le constructeur de StudentsComponent, appelez le loadWithApolloClientméthode. Le complet Student.js le fichier est ci-dessous -

import React, {Component} from 'react';
import { Link} from 'react-router-dom'

//Apollo Client
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
import gql from 'graphql-tag'
const client = new ApolloClient({
   link: new HttpLink({uri:`http://localhost:9000/graphql`}),
   cache:new InMemoryCache()
})

class Students extends Component {
   constructor(props) {
      super(props);
      this.state = {
         students:[{id:1,firstName:'test'}],
         serverTime:''
      }
      this.loadWithApolloclient().then(data => {
         this.setState({
            students:data.students,
            serverTime:data.getTime
         })
      })
   }
   
   async  loadStudents_noCache() {
      const response = await fetch('http://localhost:9000/graphql', {
         method:'POST',
         headers:{'content-type':'application/json'},
         body:JSON.stringify({query:`{
            getTime
            students {
               id
               firstName
            }
         }`})
      })
      const rsponseBody =  await response.json();
      return rsponseBody.data;
   }
   
   async loadWithApolloclient() {
      console.log("inside apollo client function")
      const query = gql`{
         getTime
         students {
            id
            firstName
         }
      }`;
      const {data} = await  client.query({query})
      return data;
   }
   
   render() {
      return(
         <div>
            <h3>Time from GraphQL server :{this.state.serverTime}</h3>
            <p>Following Students Found </p>
            <div>
               <ul>
                  {
                     this.state.students.map(s => {
                        return(
                           <li key = {s.id}>
                              {s.firstName}
                           </li>
                        )
                     })
                  }
               </ul>
            </div>
         </div>
      )
   }
}
export default Students

Étape 6 - Exécutez l'application React avec npm start

Vous pouvez tester l'application react en passant de l'onglet d'accueil à l'onglet étudiants. Une fois que l'onglet étudiants est chargé avec les données du serveur. Il mettra en cache les données. Vous pouvez le tester en passant plusieurs fois de l'onglet Accueil à l'onglet Élèves. La sortie sera comme indiqué ci-dessous -

Si vous avez d'abord chargé la page des élèves en saisissant l'URL, http://localhost:3000/#/students, vous pouvez voir que le temps de chargement de l'application react et de GraphQL serait approximativement le même. Après cela, si vous passez en vue d'accueil et revenez sur le serveur GraphQL, l'heure ne changera pas. Cela montre que les données sont mises en cache.

Étape 7 - Changez l'appel loadWithApolloclient pour loadStudents_noCache

Si vous modifiez la méthode de chargement en loadStudents_noCachedans le constructeur de StudentComponent, la sortie ne mettra pas en cache les données. Cela montre la différence entre la mise en cache et la non-mise en cache.

this.loadStudents_noCache().then(data => {
   this.setState({
      students:data.students,
      serverTime:data.getTime
   })
})

À partir de la sortie ci-dessus, il est clair que si vous basculez entre les onglets, l'heure du serveur graphql sera toujours la plus récente, ce qui signifie que les données ne sont pas mises en cache.