GraphQL-キャッシング
キャッシングは、と呼ばれる一時ストレージ領域にデータを保存するプロセスです。 cache。最近アクセスしたページに戻ると、ブラウザは元のサーバーではなくキャッシュからそれらのファイルを取得できます。これにより、追加のトラフィックの負担から時間とネットワークを節約できます。
GraphQLと対話するクライアントアプリケーションは、最後にデータをキャッシュする責任があります。このための1つの可能なパターンは、idなどのフィールドをグローバル一意識別子として予約することです。
インメモリキャッシュ
InMemoryCacheは、Reduxなどの他のライブラリを使用せずにGraphQLクライアントアプリケーションで一般的に使用される正規化されたデータストアです。
ApolloClientでInMemoryCacheを使用するためのサンプルコードを以下に示します-
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で、ホームタブ用と学生用の2つのタブを備えたシングルページアプリケーションを作成します。[学生]タブは、GraphQLサーバーAPIからデータをロードします。ユーザーが[ホーム]タブから[学生]タブに移動すると、アプリケーションは学生データを照会します。結果のデータは、アプリケーションによってキャッシュされます。
また、を使用してサーバー時間をクエリします getTimeページがキャッシュされているかどうかを確認するフィールド。データがキャッシュから返される場合、ページにはサーバーに送信された最初のリクエストの時刻が表示されます。データがサーバーに対して行われた新しい要求の結果である場合、データは常にサーバーからの最新の時刻を示します。
サーバーのセットアップ
サーバーを設定する手順は次のとおりです-
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
フォルダを作成する cache-server-app。ディレクトリを次のように変更します 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を参照してください。ターミナルでコマンドnpmstartを実行します。サーバーは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
これにより、一般的なReactアプリケーションに必要なすべてのものがインストールされます。ザ・npx utility そして create-react-appツールは、hello-world-clientという名前のプロジェクトを作成します。インストールが完了したら、VSCodeでプロジェクトを開きます。
次のコマンドを使用して、反応するルーターモジュールをインストールします– npm install react-router-dom。
ステップ2-hello-world-clientを起動します
ターミナルの現在のフォルダーパスをhello-world-clientに変更します。npm startと入力して、プロジェクトを起動します。これにより、ポート3000で開発サーバーが実行され、ブラウザが自動的に開き、インデックスページが読み込まれます。
これは、以下のスクリーンショットに示されています-
ステップ3-Apolloクライアントライブラリをインストールする
Apolloクライアントをインストールするには、新しいターミナルを開き、現在のプロジェクトフォルダーパスに移動します。次のコマンドを入力します-
npm install apollo-boost graphql
これにより、クライアント側のgraphqlライブラリとApolloBoostパッケージがダウンロードされます。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ファイルのアプリコンポーネントを変更する
単純なreactアプリケーションの場合、維持する必要があるのは index.js に src フォルダと index.htmlパブリックフォルダ内。自動生成された他のすべてのファイルは削除できます。
ディレクトリ構造を以下に示します-
hello-world-client /
-->node_modules
-->public
index.html
-->src
index.js
students.js
-->package.json
Studentコンポーネントを含むファイルstudents.jsを追加します。学生の詳細は、学生コンポーネントを介して取得されます。アプリコンポーネントでは、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でコンポーネントの学生を編集する
Student Componentでは、次の2つのアプローチを使用してデータをロードします-
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リソースをフェッチするためのシンプルなインターフェイスです。Fetchを使用すると、古いXMLHttpRequestを使用するよりも、Web要求の作成と応答の処理が簡単になります。次のメソッドは、fetchapiを使用してデータを直接ロードする方法を示しています。
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;
}
StudentComponentのコンストラクターで、 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-npmstartでReactアプリケーションを実行する
ホームタブから学生タブに切り替えることで、reactアプリケーションをテストできます。学生タブにサーバーからのデータがロードされたら。データをキャッシュします。[自宅]タブから[学生]タブに複数回切り替えることでテストできます。出力は以下のようになります−
最初にURLを入力して学生ページを読み込んだ場合は、 http://localhost:3000/#/students、reactアプリとGraphQLの読み込み時間はほぼ同じであることがわかります。その後、ホームビューに切り替えてGraphQLサーバーに戻っても、時間は変わりません。これは、データがキャッシュされていることを示しています。
ステップ7-loadWithApolloclient呼び出しをloadStudents_noCacheに変更します
ロード方法をに変更した場合 loadStudents_noCacheStudentComponentのコンストラクターでは、出力はデータをキャッシュしません。これは、キャッシュと非キャッシュの違いを示しています。
this.loadStudents_noCache().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
上記の出力から、タブ間を行ったり来たりすると、graphqlサーバーからの時間が常に最新になり、データがキャッシュされないことがわかります。