GraphQL - Bộ nhớ đệm
Bộ nhớ đệm là quá trình lưu trữ dữ liệu trong một vùng lưu trữ tạm thời được gọi là cache. Khi bạn quay lại trang mà bạn đã truy cập gần đây, trình duyệt có thể lấy các tệp đó từ bộ nhớ cache thay vì máy chủ ban đầu. Điều này tiết kiệm thời gian của bạn và mạng khỏi gánh nặng của lưu lượng bổ sung.
Các ứng dụng khách tương tác với GraphQL chịu trách nhiệm lưu trữ dữ liệu vào bộ nhớ đệm ở cuối của chúng. Một mô hình có thể xảy ra cho điều này là dành một trường, như id, để làm số nhận dạng duy nhất trên toàn cầu.
Bộ nhớ đệm InMemory
InMemoryCache là một kho lưu trữ dữ liệu chuẩn hóa thường được sử dụng trong các ứng dụng khách GraphQL mà không cần sử dụng thư viện khác như Redux.
Mã mẫu để sử dụng InMemoryCache với ApolloClient được đưa ra dưới đây:
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const cache = new InMemoryCache();
const client = new ApolloClient({
link: new HttpLink(),
cache
});
Hàm tạo InMemoryCache nhận một đối tượng cấu hình tùy chọn với các thuộc tính để tùy chỉnh bộ nhớ cache của bạn.
Sr.No. | Mô tả về Thông Số |
---|---|
1 | addTypename Một boolean để xác định xem có thêm __typename vào tài liệu hay không (mặc định: true) |
2 | dataIdFromObject Một hàm nhận một đối tượng dữ liệu và trả về một mã định danh duy nhất được sử dụng khi chuẩn hóa dữ liệu trong cửa hàng |
3 | fragmentMatcher Theo mặc định, InMemoryCache sử dụng trình so khớp phân đoạn heuristic |
4 | cacheRedirects Bản đồ các chức năng để chuyển hướng một truy vấn đến một mục nhập khác trong bộ đệm trước khi một yêu cầu diễn ra. |
Hình minh họa
Chúng tôi sẽ tạo một ứng dụng trang đơn trong ReactJS với hai tab - một cho tab trang chủ và một cho sinh viên. Tab sinh viên sẽ tải dữ liệu từ API máy chủ GraphQL. Ứng dụng sẽ truy vấn dữ liệu sinh viên khi người dùng điều hướng từ tab trang chủ đến tab sinh viên. Dữ liệu kết quả sẽ được ứng dụng lưu vào bộ nhớ đệm.
Chúng tôi cũng sẽ truy vấn thời gian sử dụng máy chủ getTimetrường để xác minh xem trang có được lưu vào bộ nhớ đệm không. Nếu dữ liệu được trả về từ bộ nhớ cache, trang sẽ hiển thị thời điểm yêu cầu đầu tiên được gửi đến máy chủ. Nếu dữ liệu là kết quả của một yêu cầu mới được gửi đến máy chủ, nó sẽ luôn hiển thị thời gian mới nhất từ máy chủ.
Thiết lập máy chủ
Sau đây là các bước để thiết lập máy chủ -
Bước 1 - Tải xuống và cài đặt các phụ thuộc bắt buộc cho dự án
Tạo một thư mục cache-server-app. Thay đổi thư mục của bạn thành cache-server-app từ thiết bị đầu cuối. Làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.
Bước 2 - Tạo một lược đồ
Thêm vào schema.graphql tập tin trong thư mục dự án cache-server-app và thêm mã sau:
type Query {
students:[Student]
getTime:String
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
}
Bước 3 - Thêm trình phân giải
Tạo một tệp giải quyết tệp tin.js trong thư mục dự án và thêm mã sau:
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}
Bước 4 - Chạy ứng dụng
Tạo tệp server.js. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sẽ sử dụng GraphiQL làm client để kiểm tra ứng dụng.
Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình soạn thảo -
{
getTime
students {
id
firstName
}
}
Câu trả lời mẫu hiển thị tên sinh viên và thời gian máy chủ.
{
"data": {
"getTime": "22:18:42",
"students": [
{
"id": "S1001",
"firstName": "Mohtashim"
},
{
"id": "S1002",
"firstName": "Kannan"
},
{
"id": "S1003",
"firstName": "Kiran"
}
]
}
}
Thiết lập ứng dụng khách ReactJS
Mở một thiết bị đầu cuối mới cho khách hàng. Thiết bị đầu cuối của máy chủ phải được duy trì chạy trước khi thực thi ứng dụng khách. Ứng dụng React sẽ chạy trên cổng số 3000 và ứng dụng máy chủ trên cổng số 9000.
Bước 1 - Tạo ứng dụng React
Trong thiết bị đầu cuối máy khách, nhập lệnh sau:
npx create-react-app hello-world-client
Điều này sẽ cài đặt mọi thứ cần thiết cho một ứng dụng phản ứng điển hình. Cácnpx utility và create-react-appcông cụ tạo một dự án với tên hello-world-client. Sau khi cài đặt xong, hãy mở dự án trong VSCode.
Cài đặt mô-đun bộ định tuyến để phản ứng bằng cách sử dụng lệnh sau: npm install react-router-dom.
Bước 2 - Bắt đầu hello-world-client
Thay đổi đường dẫn thư mục hiện tại trong terminal thành hello-world-client. Nhập npm start để khởi chạy dự án. Thao tác này sẽ chạy một máy chủ phát triển ở cổng 3000 và sẽ tự động mở trình duyệt và tải trang chỉ mục.
Điều này được hiển thị trong ảnh chụp màn hình dưới đây -
Bước 3 - Cài đặt thư viện khách hàng Apollo
Để cài đặt Ứng dụng khách Apollo, hãy mở một thiết bị đầu cuối mới và ở trong đường dẫn thư mục dự án hiện tại. Gõ lệnh sau:
npm install apollo-boost graphql
Thao tác này sẽ tải xuống các thư viện graphql cho phía máy khách và cả gói Apollo Boost. Chúng tôi có thể xác minh chéo điều này bằng cách gõ npm view apollo-boost phụ thuộc. Điều này sẽ có nhiều phụ thuộc như hình dưới đây -
{
'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'
}
Chúng ta có thể thấy rõ ràng rằng thư viện apollo-client đã được cài đặt.
Bước 4 - Sửa đổi thành phần ứng dụng trong tệp index.js
Đối với một ứng dụng phản ứng đơn giản, bạn chỉ cần giữ index.js trong src thư mục và index.htmltrong thư mục chung; tất cả các tệp khác được tạo tự động có thể bị xóa.
Cấu trúc thư mục được đưa ra dưới đây:
hello-world-client /
-->node_modules
-->public
index.html
-->src
index.js
students.js
-->package.json
Thêm một tệp bổ sung student.js sẽ chứa Thành phần Sinh viên. Thông tin chi tiết về sinh viên được tìm nạp thông qua Thành phần Sinh viên. Trong Thành phần ứng dụng, chúng tôi đang sử dụng HashRouter.
Sau đây là index.js trong ứng dụng phản ứng -
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"))
Bước 5 - Chỉnh sửa học sinh thành phần trong Students.js
Trong Hợp phần Sinh viên, chúng tôi sẽ sử dụng hai cách tiếp cận sau để tải dữ liệu:
Fetch API (loadStudents_noCache) - Điều này sẽ kích hoạt một yêu cầu mới mỗi khi nhấp vào tab sinh viên.
Apollo Client (loadWithApolloclient) - Thao tác này sẽ lấy dữ liệu từ bộ nhớ đệm.
Thêm một chức năng loadWithApolloclienttruy vấn nào cho sinh viên và thời gian từ máy chủ. Chức năng này sẽ kích hoạt bộ nhớ đệm. Ở đây chúng tôi sử dụng một hàm gql để phân tích cú pháp truy vấn.
async loadWithApolloclient() {
const query = gql`{
getTime
students {
id
firstName
}
}`;
const {data} = await client.query({query})
return data;
}
Các Fetch APIlà một giao diện đơn giản để tìm nạp tài nguyên. Tìm nạp giúp dễ dàng thực hiện các yêu cầu web và xử lý phản hồi hơn so với XMLHttpRequest cũ hơn. Phương pháp sau cho thấy việc tải dữ liệu trực tiếp bằng api tìm nạp:
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;
}
Trong hàm tạo của StudentsComponent, hãy gọi loadWithApolloClientphương pháp. Hoàn chỉnh Student.js tệp bên dưới -
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
Bước 6 - Chạy ứng dụng React với npm start
Bạn có thể kiểm tra ứng dụng phản ứng bằng cách chuyển từ tab trang chủ sang tab sinh viên. Sau khi tab sinh viên được tải với dữ liệu từ máy chủ. Nó sẽ lưu dữ liệu vào bộ nhớ cache. Bạn có thể kiểm tra nó bằng cách chuyển từ tab nhà sang tab sinh viên nhiều lần. Đầu ra sẽ như hình dưới đây -
Nếu bạn đã tải trang sinh viên đầu tiên bằng cách nhập URL, http://localhost:3000/#/students, bạn có thể thấy rằng thời gian tải cho ứng dụng phản ứng và GraphQL sẽ gần giống nhau. Sau đó, nếu bạn chuyển sang chế độ xem chính và quay lại máy chủ GraphQL, thời gian sẽ không thay đổi. Điều này cho thấy dữ liệu được lưu trong bộ nhớ cache.
Bước 7 - Thay đổi cuộc gọi loadWithApolloclient thành loadStudents_noCache
Nếu bạn thay đổi phương thức tải thành loadStudents_noCachetrong phương thức khởi tạo của StudentComponent, đầu ra sẽ không lưu dữ liệu vào bộ nhớ cache. Điều này cho thấy sự khác biệt giữa bộ nhớ đệm và không bộ nhớ đệm.
this.loadStudents_noCache().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
Từ kết quả trên, rõ ràng là nếu bạn chuyển đổi qua lại giữa các tab, thời gian từ máy chủ graphql sẽ luôn là muộn nhất có nghĩa là dữ liệu không được lưu trong bộ nhớ cache.