Graphql-caching
GraphQL-キャッシング
キャッシングは、「キャッシュ」と呼ばれる一時記憶領域にデータを保存するプロセスです。 最近アクセスしたページに戻ると、ブラウザは元のサーバーではなくキャッシュからこれらのファイルを取得できます。 これにより、時間とネットワークが追加のトラフィックの負担から節約されます。
GraphQLと対話するクライアントアプリケーションは、データを最後にキャッシュする責任があります。 このパターンの1つとして考えられるのは、likeidなどのフィールドをグローバルに一意の識別子として予約することです。
InMemoryキャッシュ
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コンストラクターは、プロパティを含むオプションの構成オブジェクトを使用して、キャッシュをカスタマイズします。
Sr.No. | Parameter & Description |
---|---|
1 |
addTypename __typenameをドキュメントに追加するかどうかを決定するブール値(デフォルト:true) |
2 |
dataIdFromObject データオブジェクトを受け取り、ストア内のデータを正規化するときに使用される一意の識別子を返す関数 |
3 |
fragmentMatcher デフォルトでは、InMemoryCacheはヒューリスティックフラグメントマッチャーを使用します |
4 |
cacheRedirects 要求が発生する前に、クエリをキャッシュ内の別のエントリにリダイレクトする関数のマップ。 |
図
ReactJSで、ホームタブ用と学生用の2つのタブを持つ単一ページのアプリケーションを作成します。 学生タブは、GraphQLサーバーAPIからデータをロードします。 ユーザーが[ホーム]タブから[学生]タブに移動すると、アプリケーションは_students_データを照会します。 結果のデータはアプリケーションによってキャッシュされます。
また、 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でプロジェクトを開きます。
次のコマンドを使用して、react用のルーターモジュールをインストールします- npm install react-router-dom 。
ステップ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の依存関係を入力します。 以下に示すように、これには多くの依存関係があります-
{
'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ファイルでアプリコンポーネントを変更する
単純な反応アプリケーションの場合、 index.js を src フォルダーに保存し、 indexl をパブリックフォルダーに保存するだけです。自動生成される他のすべてのファイルは削除できます。
ディレクトリ構造は以下のとおりです-
hello-world-client/
-->node_modules
-->public
indexl
-->src
index.js
students.js
-->package.json
学生コンポーネントを含む追加のファイルstudent.jsを追加します。 学生の詳細は、学生コンポーネントを通じて取得されます。 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でコンポーネントの生徒を編集する
学生コンポーネントでは、次の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要求を作成して応答を処理しやすくなります。 次の方法は、フェッチ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 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-_npm start_を使用してReactアプリケーションを実行する
[ホーム]タブから[学生]タブに切り替えることで、反応アプリケーションをテストできます。 学生タブにサーバーからのデータがロードされると。 データをキャッシュします。 自宅から生徒タブに複数回切り替えることでテストできます。 出力は以下のようになります-
URL、 http://localhost:3000/#/students を入力して最初に生徒のページを読み込んだ場合、反応アプリとGraphQLの読み込み時間がほぼ同じであることがわかります。 その後、ホームビューに切り替えてGraphQLサーバーに戻っても、時間は変わりません。 これは、データがキャッシュされていることを示しています。
ステップ7-loadWithApolloclient呼び出しをloadStudents_noCacheに変更します
StudentComponentのコンストラクターでloadメソッドを loadStudents_noCache に変更すると、出力はデータをキャッシュしません。 これは、キャッシュと非キャッシュの違いを示しています。
this.loadStudents_noCache().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
loadWithApolloclientを使用したReactアプリケーションの出力
上記の出力から、タブ間を切り替えると、graphqlサーバーからの時間が常に最新であり、データがキャッシュされないことがわかります。