
- 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://: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://: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://: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://: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://: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 伺服器的時間將始終是最新的,這意味著資料未被快取。