GraphQL - Almacenamiento en caché
El almacenamiento en caché es el proceso de almacenar datos en un área de almacenamiento temporal llamada cache. Cuando regresa a una página que ha visitado recientemente, el navegador puede obtener esos archivos del caché en lugar del servidor original. Esto le ahorra tiempo y a la red la carga del tráfico adicional.
Las aplicaciones cliente que interactúan con GraphQL son responsables de almacenar en caché los datos al final. Un patrón posible para esto es reservar un campo, como id, para que sea un identificador único global.
Caché de InMemory
InMemoryCache es un almacén de datos normalizado que se usa comúnmente en aplicaciones cliente GraphQL sin el uso de otra biblioteca como Redux.
El código de muestra para usar InMemoryCache con ApolloClient se proporciona a continuación:
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const cache = new InMemoryCache();
const client = new ApolloClient({
link: new HttpLink(),
cache
});
El constructor InMemoryCache toma un objeto de configuración opcional con propiedades para personalizar su caché.
No Señor. | Descripción de parámetros |
---|---|
1 | addTypename Un booleano para determinar si agregar __typename al documento (predeterminado: verdadero) |
2 | dataIdFromObject Una función que toma un objeto de datos y devuelve un identificador único que se utilizará al normalizar los datos en la tienda. |
3 | fragmentMatcher De forma predeterminada, InMemoryCache usa un comparador de fragmentos heurístico |
4 | cacheRedirects Un mapa de funciones para redirigir una consulta a otra entrada en la caché antes de que se realice una solicitud. |
Ilustración
Crearemos una aplicación de una sola página en ReactJS con dos pestañas, una para la pestaña de inicio y otra para los estudiantes. La pestaña de estudiantes cargará datos de una API de servidor GraphQL. La aplicación consultará los datos de los estudiantes cuando el usuario navegue desde la pestaña de inicio a la pestaña de estudiantes. Los datos resultantes serán almacenados en caché por la aplicación.
También consultaremos la hora del servidor usando getTimecampo para verificar si la página está almacenada en caché. Si se devuelven datos de la caché, la página mostrará la hora de la primera solicitud enviada al servidor. Si los datos son el resultado de una nueva solicitud realizada al servidor, siempre mostrará la última hora del servidor.
Configurar el servidor
Los siguientes son los pasos para configurar el servidor:
Paso 1: descargue e instale las dependencias necesarias para el proyecto
Crea una carpeta cache-server-app. Cambie su directorio a cache-server-app desde la terminal. Siga los pasos 3 a 5 explicados en el capítulo Configuración del entorno.
Paso 2: crea un esquema
Añadir schema.graphql archivo en la carpeta del proyecto cache-server-app y agregue el siguiente código -
type Query {
students:[Student]
getTime:String
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
}
Paso 3: agregar resolutores
Cree un archivo resolvers.js en la carpeta del proyecto y agregue el siguiente código:
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}
Paso 4: ejecutar la aplicación
Cree un archivo server.js. Consulte el paso 8 del capítulo Configuración del entorno. Ejecute el comando npm start en la terminal. El servidor estará funcionando en el puerto 9000. Aquí, usaremos GraphiQL como cliente para probar la aplicación.
Abra el navegador e ingrese la URL http://localhost:9000/graphiql. Escriba la siguiente consulta en el editor:
{
getTime
students {
id
firstName
}
}
La respuesta de muestra muestra los nombres de los estudiantes y la hora del servidor.
{
"data": {
"getTime": "22:18:42",
"students": [
{
"id": "S1001",
"firstName": "Mohtashim"
},
{
"id": "S1002",
"firstName": "Kannan"
},
{
"id": "S1003",
"firstName": "Kiran"
}
]
}
}
Configuración del cliente ReactJS
Abra una nueva terminal para el cliente. El terminal del servidor debe seguir funcionando antes de ejecutar la aplicación cliente. La aplicación React se ejecutará en el puerto número 3000 y la aplicación del servidor en el puerto número 9000.
Paso 1: crea una aplicación React
En la terminal del cliente, escriba el siguiente comando:
npx create-react-app hello-world-client
Esto instalará todo lo necesario para una aplicación típica de reacción. losnpx utility y create-react-appLas herramientas crean un proyecto con el nombre hello-world-client. Una vez que se complete la instalación, abra el proyecto en VSCode.
Instale los módulos del enrutador para reaccionar usando el siguiente comando: npm install react-router-dom.
Paso 2: iniciar hello-world-client
Cambie la ruta de la carpeta actual en la terminal a hello-world-client. Escriba npm start para iniciar el proyecto. Esto ejecutará un servidor de desarrollo en el puerto 3000 y automáticamente abrirá el navegador y cargará la página de índice.
Esto se muestra en la captura de pantalla que se muestra a continuación:
Paso 3: instalar las bibliotecas cliente de Apollo
Para instalar un cliente Apollo, abra una nueva terminal y esté en la ruta de la carpeta del proyecto actual. Escriba el siguiente comando:
npm install apollo-boost graphql
Esto descargará las bibliotecas graphql del lado del cliente y también el paquete Apollo Boost. Podemos verificar esto de forma cruzada escribiendo npm view apollo-boost dependencies. Esto tendrá muchas dependencias como se muestra a continuación:
{
'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'
}
Podemos ver claramente que la biblioteca apollo-client está instalada.
Paso 4: modificar el componente de la aplicación en el archivo index.js
Para una aplicación de reacción simple, solo necesita mantener el index.js en src carpeta y index.htmlen carpeta pública; todos los demás archivos que se generan automáticamente se pueden eliminar.
La estructura del directorio se da a continuación:
hello-world-client /
-->node_modules
-->public
index.html
-->src
index.js
students.js
-->package.json
Agregue un archivo adicional Students.js que contendrá el componente Students. Los detalles de los estudiantes se obtienen a través del Componente de estudiantes. En el componente de la aplicación, estamos usando un HashRouter.
Lo siguiente es el index.js en la aplicación de reacción -
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"))
Paso 5: Edite los estudiantes del componente en Students.js
En el Componente de estudiantes, usaremos los siguientes dos enfoques para cargar datos:
Fetch API (loadStudents_noCache) - Esto activará una nueva solicitud cada vez que haga clic en la pestaña del estudiante.
Apollo Client (loadWithApolloclient) - Esto obtendrá datos de la caché.
Agregar una función loadWithApolloclientqué consultas para los estudiantes y el tiempo del servidor. Esta función habilitará el almacenamiento en caché. Aquí usamos una función gql para analizar la consulta.
async loadWithApolloclient() {
const query = gql`{
getTime
students {
id
firstName
}
}`;
const {data} = await client.query({query})
return data;
}
los Fetch APIes una interfaz simple para buscar recursos. Fetch hace que sea más fácil realizar solicitudes web y manejar respuestas que con XMLHttpRequest anterior. El siguiente método muestra la carga de datos directamente usando 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;
}
En el constructor de StudentsComponent, llame al loadWithApolloClientmétodo. El completo Student.js el archivo está debajo -
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
Paso 6 - Ejecute la aplicación React con npm start
Puede probar la aplicación de reacción cambiando de la pestaña de inicio a la pestaña de estudiantes. Una vez que la pestaña de estudiantes está cargada con datos del servidor. Guardará los datos en caché. Puede probarlo cambiando de la pestaña de inicio a la de estudiantes varias veces. La salida será como se muestra a continuación:
Si ha cargado la página de los estudiantes primero escribiendo la URL, http://localhost:3000/#/students, puede ver que el tiempo de carga para la aplicación de reacción y GraphQL sería aproximadamente el mismo. Después de eso, si cambia a la vista de inicio y regresa al servidor GraphQL, la hora no cambiará. Esto muestra que los datos están almacenados en caché.
Paso 7: cambie la llamada loadWithApolloclient a loadStudents_noCache
Si cambia el método de carga a loadStudents_noCacheen el constructor de StudentComponent, la salida no almacenará en caché los datos. Esto muestra la diferencia entre almacenamiento en caché y sin almacenamiento en caché.
this.loadStudents_noCache().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
De la salida anterior, está claro que si cambia de una pestaña a otra, el tiempo del servidor graphql siempre será el último, lo que significa que los datos no se almacenan en caché.