缓存是将数据存储在名为缓存的临时存储区域中的过程.当您返回到最近访问过的页面时,浏览器可以从缓存而不是原始服务器获取这些文件.这节省了您的时间和网络,增加了额外流量的负担.
与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 在请求发生之前将查询重定向到缓存中的另一个条目的函数映射. |
插图
我们将在ReactJS中创建一个带有两个标签的单页应用程序 - 一个用于主页选项卡和另一个学生.学生选项卡将从GraphQL服务器API加载数据.当用户从主页选项卡导航到学生选项卡时,应用程序将查询学生数据.生成的数据将由应用程序缓存.
我们还将使用 getTime 字段查询服务器时间,以验证页面是否已缓存.如果从缓存返回数据,页面将显示发送到服务器的第一个请求的时间.如果数据是对服务器发出新请求的结果,则它将始终显示服务器的最新时间.
设置服务器
以下是设置服务器的步骤 :
步骤1 : 号;下载并安装项目所需的依赖项
创建文件夹 cache-server-app .从终端将目录更改为 cache-server-app .按照环境设置章节中说明的步骤3到5进行操作.
步骤2 : 创建架构
在项目文件夹 cache-server-app 中添加 schema.graphql 文件并添加以下代码 :
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-react-app 工具创建一个名为hello-world-client的项目.安装完成后,在VSCode中打开项目.
使用以下命令安装路由器模块以进行响应 - npm install react-router-dom .
第2步和第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 dependencies来交叉验证.这将有许多依赖关系,如下所示 :
{ '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文件中的App组件
对于简单的反应应用程序,您只需要将 index.js 保留在 src 公用文件夹中的文件夹和 index.html ;可以删除自动生成的所有其他文件.
目录结构在下面和下面给出;
hello-world-client / -->node_modules -->public index.html -->src index.js students.js -->package.json
添加一个包含Students Component的附加文件students.js.学生详细信息通过学生组件获取.在App Component中,我们使用的是HashRouter.
以下是反应应用中的 index.js :
import React, {Component} from 'react';import ReactDOM from 'react-dom';import {HashRouter, Route, Link} from 'react-router-dom'//componentsimport Students from './students'class App extends Component { render() { return() }}function getTime() { var d = new Date(); return d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()}const routes =Home !!
Welcome to React Application !!
ReactDOM.render(routes, document.querySelector("#root")) Time from react app:{getTime()}
Home Students
Step 5 : 编辑Students.js中的组件学生
在学生组件中,我们将使用以下两种方法来加载数据 :
获取API(loadStudents_noCache) : 这会在每次点击学生标签时触发新请求.
Apollo Client(loadWithApolloclient) : 这将从缓存中获取数据.
添加一个函数 loadWithApolloclient 从服务器查询学生和时间.此功能将启用缓存.这里我们使用gql函数来解析查询.
async loadWithApolloclient() { const query = gql`{ getTime students { id firstName } }`; const {data} = await client.query({query}) return data;}
Fetch API 是一个用于获取资源的简单界面.与旧的XMLHttpRequest相比,Fetch使Web请求和处理响应变得更容易.以下方法显示使用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 Clientimport {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() }}export default StudentsTime from GraphQL server :{this.state.serverTime}
Following Students Found
{ this.state.students.map(s => { return(
- {s.firstName}
) }) }
步骤6 : 去;使用 npm start 运行React应用程序
您可以通过从主页选项卡切换到学生选项卡来测试反应应用程序.一旦学生选项卡加载了来自服务器的数据.它将缓存数据.您可以通过多次从home切换到student选项卡来测试它.输出将如下所示 :
如果您通过输入URL http://localhost:3000/#/students 首先加载了学生页面,您可以看到react app和GraphQL的加载时间大致相同相同.之后,如果切换到主视图并返回到GraphQL服务器,则时间不会更改.这表示数据已缓存.
步骤7 : 更改loadWithApolloclient调用loadStudents_noCache
如果在StudentComponent的构造函数中将load方法更改为 loadStudents_noCache ,则输出将不会缓存数据.这显示了缓存和非缓存之间的区别.
this.loadStudents_noCache().then(data => { this.setState({ students:data.students, serverTime:data.getTime })})
从上面的输出可以看出,如果你来回切换在选项卡之间,来自graphql server的时间总是最新的,这意味着数据不会被缓存.