Учебники

GraphQL — Кэширование

Кэширование — это процесс хранения данных во временной области хранения, называемой кешем . Когда вы возвращаетесь на страницу, которую вы недавно посещали, браузер может получать эти файлы из кэша, а не с исходного сервера. Это экономит ваше время и сеть от бремени дополнительного трафика.

Клиентские приложения, взаимодействующие с GraphQL, несут ответственность за кэширование данных в их конце. Одним из возможных шаблонов для этого является резервирование поля, такого как id, в качестве глобального уникального идентификатора.

InMemory Cache

InMemoryCache — это нормализованное хранилище данных, обычно используемое в клиентских приложениях GraphQL без использования других библиотек, таких как Redux.

Пример кода для использования InMemoryCache с ApolloClient приведен ниже —

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

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

Конструктор InMemoryCache принимает необязательный объект конфигурации со свойствами для настройки вашего кэша.

Sr.No. Параметр и описание
1

addTypename

Логическое значение, определяющее, следует ли добавлять __typename в документ (по умолчанию: true)

2

dataIdFromObject

Функция, которая принимает объект данных и возвращает уникальный идентификатор, который будет использоваться при нормализации данных в хранилище.

3

fragmentMatcher

По умолчанию InMemoryCache использует эвристический алгоритм сопоставления фрагментов.

4

cacheRedirects

Карта функций для перенаправления запроса на другую запись в кеше до его выполнения.

addTypename

Логическое значение, определяющее, следует ли добавлять __typename в документ (по умолчанию: true)

dataIdFromObject

Функция, которая принимает объект данных и возвращает уникальный идентификатор, который будет использоваться при нормализации данных в хранилище.

fragmentMatcher

По умолчанию InMemoryCache использует эвристический алгоритм сопоставления фрагментов.

cacheRedirects

Карта функций для перенаправления запроса на другую запись в кеше до его выполнения.

иллюстрация

Мы создадим одностраничное приложение в ReactJS с двумя вкладками — одна для домашней вкладки и другая для студентов. Вкладка студентов будет загружать данные из API сервера GraphQL. Приложение будет запрашивать данные о студентах, когда пользователь переходит с домашней вкладки на вкладку студентов. Полученные данные будут кэшироваться приложением.

Мы также запросим время сервера, используя поле getTime, чтобы проверить, кэширована ли страница. Если данные возвращаются из кэша, на странице будет отображаться время самого первого запроса, отправленного на сервер. Если данные являются результатом нового запроса к серверу, он всегда будет показывать самое последнее время с сервера.

Настройка сервера

Ниже приведены шаги для настройки сервера:

Шаг 1 — Загрузите и установите необходимые зависимости для проекта

Создайте папку cache-server-app . Измените свой каталог на кеш-сервер-приложение из терминала. Выполните шаги с 3 по 5, описанные в главе «Настройка среды».

Шаг 2 — Создание схемы

Добавьте файл schema.graphql в папку проекта cache-server-app и добавьте следующий код —

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

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

Шаг 3 — Добавить резольверы

Создайте файл resolvers.js в папке проекта и добавьте следующий код:

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}

Шаг 4 — Запустите приложение

Создайте файл server.js. См. Шаг 8 в главе «Настройка среды». Выполните команду npm start в терминале. Сервер будет работать на 9000 портов. Здесь мы будем использовать GraphiQL в качестве клиента для тестирования приложения.

Откройте браузер и введите URL-адрес http: // localhost: 9000 / graphiql . Введите следующий запрос в редакторе —

{
   getTime
   students {
      id
      firstName
   }
}

Пример ответа показывает имена учеников и время сервера.

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

Настройка клиента ReactJS

Откройте новый терминал для клиента. Терминал сервера должен быть запущен до выполнения клиентского приложения. Приложение React будет работать на порту с номером 3000, а приложение сервера — на порту с номером 9000.

Шаг 1 — Создание приложения React

В клиентском терминале введите следующую команду —

npx create-react-app hello-world-client

Это установит все необходимое для типичного реагирующего приложения. Утилита npx и инструменты create-реагировать на приложение создают проект с именем hello-world-client. После завершения установки откройте проект в VSCode.

Установите модули маршрутизатора для реакции, используя следующую команду — npm install response-router-dom .

Шаг 2 — Запустите hello-world-client

Измените текущий путь к папке в терминале на hello-world-client. Наберите npm start, чтобы запустить проект. Это запустит сервер разработки на порту 3000 и автоматически откроет браузер и загрузит страницу индекса.

Это показано на скриншоте ниже.

Скриншот запуска браузера проекта

Шаг 3 — Установите клиентские библиотеки Apollo

Чтобы установить клиент Apollo, откройте новый терминал и укажите путь к папке текущего проекта. Введите следующую команду —

npm install apollo-boost graphql

Это загрузит библиотеки graphql для клиентской части, а также пакет Apollo Boost. Мы можем перекрестно проверить это, набрав npm view apollo-boost зависимости. Это будет иметь много зависимостей, как показано ниже —

{ 
   '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' 
}

Мы ясно видим, что библиотека apollo-client установлена.

Шаг 4. Изменение компонента приложения в файле index.js

Для простого приложения реагирования вам нужно только сохранить index.js в папке src и index.html в общей папке; все остальные файлы, которые создаются автоматически, могут быть удалены.

Структура каталогов приведена ниже —

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

Добавьте дополнительный файл student.js, который будет содержать компонент Students. Сведения об ученике извлекаются через компонент ученика. В компоненте приложения мы используем HashRouter.

Ниже приводится index.js в приложении реагировать —

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"))

Шаг 5 — Редактирование компонентов студентов в Students.js

В Студенческом Компоненте мы будем использовать следующие два подхода для загрузки данных:

  • Fetch API (loadStudents_noCache) — это будет запускать новый запрос каждый раз, когда нажимает вкладку ученика.

  • Клиент Apollo (loadWithApolloclient) — будет извлекать данные из кэша.

Fetch API (loadStudents_noCache) — это будет запускать новый запрос каждый раз, когда нажимает вкладку ученика.

Клиент Apollo (loadWithApolloclient) — будет извлекать данные из кэша.

Добавьте функцию loadWithApolloclient, которая запрашивает студентов и время с сервера. Эта функция включит кеширование. Здесь мы используем функцию gql для разбора запроса.

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

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

Fetch API — это простой интерфейс для извлечения ресурсов. Fetch облегчает создание веб-запросов и обработку ответов, чем при использовании более старого XMLHttpRequest. Следующий метод показывает загрузку данных напрямую с помощью 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;
}

В конструкторе StudentsComponent вызовите метод loadWithApolloClient . Полный файл Student.js находится ниже —

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

Шаг 6 — Запустите приложение React с npm start

Вы можете протестировать приложение реагирования, переключившись с домашней вкладки на вкладку студентов. После того, как вкладка студентов загружается с данными с сервера. Это будет кешировать данные. Вы можете проверить это, переключаясь из дома на вкладку студентов несколько раз. Вывод будет таким, как показано ниже —

Выходная реакция приложения с запуском NPM

Если вы сначала загрузили страницу учеников, введя URL-адрес http: // localhost: 3000 / # / Students, вы увидите, что время загрузки приложения реагировать и GraphQL будет примерно одинаковым. После этого, если вы переключитесь в режим домашнего просмотра и вернетесь на сервер GraphQL, время не изменится. Это показывает, что данные кэшируются.

Шаг 7 — Измените вызов loadWithApolloclient на loadStudents_noCache

Если вы измените метод загрузки на loadStudents_noCache в конструкторе StudentComponent, выходные данные не будут кэшироваться в данных. Это показывает разницу между кэшированием и отсутствием кэширования.

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

Выходное реагирующее приложение с loadWithApolloclient

Из вышеприведенного вывода ясно, что если вы переключаетесь между вкладками, время с сервера GraphQL всегда будет самым последним, что означает, что данные не кэшируются.