GraphQL - Cache
Cache é o processo de armazenamento de dados em uma área de armazenamento temporário chamada cache. Quando você retorna a uma página que visitou recentemente, o navegador pode obter esses arquivos do cache em vez do servidor original. Isso economiza seu tempo e rede da carga de tráfego adicional.
Os aplicativos cliente que interagem com o GraphQL são responsáveis pelo armazenamento em cache dos dados em sua extremidade. Um padrão possível para isso é reservar um campo, como id, para ser um identificador globalmente exclusivo.
Cache InMemory
InMemoryCache é um armazenamento de dados normalizado comumente usado em aplicativos cliente GraphQL sem o uso de outra biblioteca como Redux.
O código de amostra para usar InMemoryCache com ApolloClient é fornecido abaixo -
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const cache = new InMemoryCache();
const client = new ApolloClient({
link: new HttpLink(),
cache
});
O construtor InMemoryCache usa um objeto de configuração opcional com propriedades para personalizar seu cache.
Sr. Não. | Parâmetro e Descrição |
---|---|
1 | addTypename Um booleano para determinar se deve ser adicionado __typename ao documento (padrão: verdadeiro) |
2 | dataIdFromObject Uma função que pega um objeto de dados e retorna um identificador único para ser usado ao normalizar os dados na loja |
3 | fragmentMatcher Por padrão, o InMemoryCache usa um matcher de fragmento heurístico |
4 | cacheRedirects Um mapa de funções para redirecionar uma consulta para outra entrada no cache antes que uma solicitação ocorra. |
Ilustração
Criaremos um aplicativo de página única no ReactJS com duas guias - uma para a guia inicial e outra para alunos. A guia de alunos carregará dados de uma API do servidor GraphQL. O aplicativo consultará os dados dos alunos quando o usuário navegar da guia inicial para a guia dos alunos. Os dados resultantes serão armazenados em cache pelo aplicativo.
Também consultaremos o tempo do servidor usando getTimecampo para verificar se a página está em cache. Se os dados forem retornados do cache, a página exibirá a hora da primeira solicitação enviada ao servidor. Se os dados forem resultado de uma nova solicitação feita ao servidor, ele sempre mostrará a hora mais recente do servidor.
Configurando o Servidor
A seguir estão as etapas para configurar o servidor -
Etapa 1 - Baixe e instale as dependências necessárias para o projeto
Crie uma pasta cache-server-app. Mude seu diretório para cache-server-app do terminal. Siga as etapas 3 a 5 explicadas no capítulo Configuração do ambiente.
Etapa 2 - Criar um esquema
Adicionar schema.graphql arquivo na pasta do projeto cache-server-app e adicione o seguinte código -
type Query {
students:[Student]
getTime:String
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
}
Etapa 3 - Adicionar resolvedores
Crie um arquivo resolvers.js na pasta do projeto e adicione o seguinte 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}
Etapa 4 - Executar o aplicativo
Crie um arquivo server.js. Consulte a etapa 8 no capítulo Configuração de ambiente. Execute o comando npm start no terminal. O servidor estará instalado e funcionando na porta 9000. Aqui, usaremos GraphiQL como um cliente para testar o aplicativo.
Abra o navegador e digite o URL http://localhost:9000/graphiql. Digite a seguinte consulta no editor -
{
getTime
students {
id
firstName
}
}
O exemplo de resposta mostra os nomes dos alunos e o horário do servidor.
{
"data": {
"getTime": "22:18:42",
"students": [
{
"id": "S1001",
"firstName": "Mohtashim"
},
{
"id": "S1002",
"firstName": "Kannan"
},
{
"id": "S1003",
"firstName": "Kiran"
}
]
}
}
Configurando o ReactJS Client
Abra um novo terminal para o cliente. O terminal do servidor deve ser mantido em execução antes de executar o aplicativo cliente. O aplicativo React será executado na porta número 3000 e o aplicativo do servidor na porta número 9000.
Etapa 1 - Criar um aplicativo React
No terminal do cliente, digite o seguinte comando -
npx create-react-app hello-world-client
Isso instalará tudo o que é necessário para um aplicativo típico de reação. onpx utility e create-react-appferramentas criam um projeto com o nome hello-world-client. Assim que a instalação for concluída, abra o projeto no VSCode.
Instale os módulos do roteador para reagir usando o seguinte comando - npm install react-router-dom.
Etapa 2 - Iniciar o cliente hello-world
Altere o caminho da pasta atual no terminal para hello-world-client. Digite npm start para iniciar o projeto. Isso executará um servidor de desenvolvimento na porta 3000, abrirá automaticamente o navegador e carregará a página de índice.
Isso é mostrado na imagem abaixo -
Etapa 3 - Instale as bibliotecas cliente Apollo
Para instalar um cliente Apollo, abra um novo terminal e esteja no caminho da pasta do projeto atual. Digite o seguinte comando -
npm install apollo-boost graphql
Isso fará o download das bibliotecas Graphql para o lado do cliente e também do pacote Apollo Boost. Podemos verificar isso digitando npm view apollo-boost dependencies. Isso terá muitas dependências, conforme mostrado abaixo -
{
'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 a biblioteca cliente-apollo está instalada.
Etapa 4 - Modificar o componente do aplicativo no arquivo index.js
Para uma aplicação simples de reação, você só precisa manter o index.js dentro src pasta e index.htmlem pasta pública; todos os outros arquivos gerados automaticamente podem ser removidos.
A estrutura do diretório é fornecida abaixo -
hello-world-client /
-->node_modules
-->public
index.html
-->src
index.js
students.js
-->package.json
Adicione um arquivo adicional students.js que conterá o componente Students. Os detalhes do aluno são obtidos por meio do Componente do aluno. No componente de aplicativo, estamos usando um HashRouter.
A seguir está o index.js na aplicação de reação -
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"))
Etapa 5 - Editar Alunos de Componente em Students.js
No Componente de alunos, usaremos as duas abordagens a seguir para carregar dados -
Fetch API (loadStudents_noCache) - Isso irá disparar uma nova solicitação toda vez que clicar na guia do aluno.
Apollo Client (loadWithApolloclient) - Isso irá buscar dados do cache.
Adicionar uma função loadWithApolloclientquais consultas para alunos e tempo do servidor. Esta função habilitará o cache. Aqui, usamos uma função gql para analisar a consulta.
async loadWithApolloclient() {
const query = gql`{
getTime
students {
id
firstName
}
}`;
const {data} = await client.query({query})
return data;
}
o Fetch APIé uma interface simples para buscar recursos. Fetch torna mais fácil fazer solicitações da web e lidar com respostas do que com o XMLHttpRequest mais antigo. O método a seguir mostra o carregamento de dados diretamente 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;
}
No construtor de StudentsComponent, chame o loadWithApolloClientmétodo. O completo Student.js o arquivo está abaixo -
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
Etapa 6 - Executar o aplicativo React com npm start
Você pode testar o aplicativo Rea, alternando da guia inicial para a guia alunos. Assim que a guia de alunos for carregada com os dados do servidor. Ele armazenará os dados em cache. Você pode testá-lo alternando da guia casa para a guia de alunos várias vezes. A saída será como mostrado abaixo -
Se você carregou a página dos alunos primeiro digitando o URL, http://localhost:3000/#/students, você pode ver que o tempo de carregamento para o app react e GraphQL seria aproximadamente o mesmo. Depois disso, se você alternar para a visualização inicial e retornar ao servidor GraphQL, a hora não mudará. Isso mostra que os dados estão armazenados em cache.
Etapa 7 - Alterar a chamada loadWithApolloclient para loadStudents_noCache
Se você alterar o método de carregamento para loadStudents_noCacheno construtor de StudentComponent, a saída não armazenará os dados em cache. Isso mostra a diferença entre armazenamento em cache e não armazenamento em cache.
this.loadStudents_noCache().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
A partir da saída acima, fica claro que se você alternar entre as guias, o tempo do servidor graphql será sempre o mais recente, o que significa que os dados não são armazenados em cache.