- GraphQL 教程
- GraphQL - 首页
- GraphQL - 简介
- GraphQL - 环境搭建
- GraphQL - 架构
- GraphQL - 应用组件
- GraphQL - 示例
- GraphQL - 类型系统
- GraphQL - 模式
- GraphQL - 解析器
- GraphQL - 查询
- GraphQL - 变更
- GraphQL - 验证
- GraphQL - JQuery 集成
- GraphQL - React 集成
- GraphQL - Apollo Client
- GraphQL - 客户端身份验证
- GraphQL - 缓存
- GraphQL 有用资源
- GraphQL - 快速指南
- GraphQL - 有用资源
- GraphQL - 讨论
GraphQL - 缓存
缓存是指将数据存储在称为缓存的临时存储区域中的过程。当您返回到最近访问过的页面时,浏览器可以从缓存中获取这些文件,而不是从原始服务器获取。这样可以节省您的时间,并减轻网络的额外流量负担。
与 GraphQL 交互的客户端应用程序负责在其端缓存数据。一种可能的模式是保留一个字段,例如 id,作为全局唯一标识符。
内存缓存
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 构造函数接受一个可选的配置对象,其中包含用于自定义缓存的属性。
序号 | 参数及描述 |
---|---|
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 作为客户端来测试应用程序。
打开浏览器并输入 URLhttps://127.0.0.1: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
这将安装典型 React 应用程序所需的一切。npx 实用程序和create-react-app工具创建了一个名为 hello-world-client 的项目。安装完成后,在 VSCode 中打开项目。
使用以下命令安装 React 的路由模块 – npm install react-router-dom。
步骤 2 - 启动 hello-world-client
在终端中更改当前文件夹路径到 hello-world-client。键入 npm start 以启动项目。这将在 3000 端口运行开发服务器,并自动打开浏览器并加载索引页面。
这在下面给出的屏幕截图中显示:
步骤 3 - 安装 Apollo Client 库
要安装 Apollo Client,请打开一个新终端并位于当前项目文件夹路径中。键入以下命令:
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 组件
对于简单的 React 应用程序,您只需要保留src文件夹中的index.js和public文件夹中的index.html;所有其他自动生成的 文件都可以删除。
目录结构如下所示:
hello-world-client / -->node_modules -->public index.html -->src index.js students.js -->package.json
添加一个额外的文件students.js,它将包含 Students 组件。学生详细信息通过 Student 组件获取。在 App 组件中,我们使用 HashRouter。
以下是 React 应用程序中的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 中的组件 Students
在 Students 组件中,我们将使用以下两种方法加载数据:
Fetch 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('https://127.0.0.1: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:`https://127.0.0.1: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('https://127.0.0.1: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 - 使用npm start运行 React 应用程序
您可以通过在主页选项卡和学生选项卡之间切换来测试 React 应用程序。一旦学生选项卡从服务器加载了数据。它将缓存数据。您可以通过多次在主页和学生选项卡之间切换来测试它。输出将如下所示:
如果您首先通过键入 URLhttps://127.0.0.1:3000/#/students加载了学生页面,您可以看到 React 应用程序和 GraphQL 的加载时间大致相同。之后,如果您切换到主页视图并返回到 GraphQL 服务器,时间将不会改变。这表明数据已缓存。
步骤 7 - 将 loadWithApolloclient 调用更改为 loadStudents_noCache
如果将 StudentComponent 构造函数中的加载方法更改为loadStudents_noCache,则输出将不会缓存数据。这显示了缓存和非缓存之间的区别。
this.loadStudents_noCache().then(data => { this.setState({ students:data.students, serverTime:data.getTime }) })
从以上输出可以看出,如果您在选项卡之间来回切换,来自 graphql 服务器的时间将始终是最新的,这意味着数据未被缓存。