GraphQL-クイックガイド
GraphQLは、RESTfulAPI呼び出しを最適化するためにFacebookによって開発されたオープンソースのサーバーサイドテクノロジーです。これは、実行エンジンであり、データクエリ言語です。この章では、GraphQLを使用する利点について説明します。
GraphQLが選ばれる理由
RESTful APIは、明確で適切に構造化されたリソース指向のアプローチに従います。ただし、データがより複雑になると、ルートは長くなります。1回のリクエストでデータを取得できない場合があります。ここでGraphQLが便利です。GraphQLは、データをトラバース、取得、および変更するための強力なクエリ構文を使用して、グラフの形式でデータを構造化します。
以下は、GraphQLクエリ言語を使用する利点です-
あなたが欲しいものを尋ねてください-そしてそれを手に入れてください
GraphQLクエリをAPIに送信して、必要なものを正確に取得します。GraphQLクエリは、常に予測可能な結果を返します。GraphQLを使用するアプリケーションは、高速で安定しています。Restfulサービスとは異なり、これらのアプリケーションはサーバーからフェッチする必要のあるデータを制限できます。
次の例は、これをよりよく理解するのに役立ちます-
属性id、firstName、lastName、collegeNameを持つビジネスオブジェクトStudentについて考えてみましょう。モバイルアプリケーションがfirstNameとidのみをフェッチする必要があるとします。/ api / v1 / studentsのようなRESTエンドポイントを設計すると、studentオブジェクトのすべてのフィールドのデータをフェッチすることになります。これは、データがRESTfulサービスによってオーバーフェッチされることを意味します。この問題は、GraphQLを使用することで解決できます。
以下に示すGraphQLクエリについて考えてみます-
{
students {
id
firstName
}
}
これにより、idフィールドとfirstnameフィールドの値のみが返されます。クエリは、学生オブジェクトの他の属性の値をフェッチしません。上に示したクエリの応答は次のとおりです-
{
"data": {
"students": [
{
"id": "S1001",
"firstName": "Mohtashim"
},
{
"id": "S1002",
"firstName": "Kannan"
}
]
}
}
1回のリクエストで多くのリソースを取得
GraphQLクエリは、関連するビジネスオブジェクトをスムーズに取得するのに役立ちますが、通常のRESTAPIでは複数のURLからロードする必要があります。GraphQL APIは、アプリケーションに必要なすべてのデータを1回のリクエストでフェッチします。GraphQLを使用するアプリケーションは、低速のモバイルネットワーク接続でも迅速に実行できます。
名前と場所という属性を持つもう1つのビジネスオブジェクトであるCollegeについて考えてみましょう。学生のビジネス・オブジェクトには、大学のオブジェクトとの対応関係を持っています。学生とその大学の詳細を取得するためにRESTAPIを使用する場合、サーバーに対して/ api / v1 / studentsと/ api / v1 / collegesのように2つのリクエストを行うことになります。これにより、リクエストごとにデータのフェッチが不足します。そのため、モバイルアプリケーションは、目的のデータを取得するためにサーバーに対して複数の呼び出しを行う必要があります。
ただし、モバイルアプリケーションは、GraphQLを使用して、1回のリクエストでStudentオブジェクトとCollegeオブジェクトの両方の詳細をフェッチできます。
以下は、データをフェッチするためのGraphQLクエリです-
{
students{
id
firstName
lastName
college{
name
location
}
}
}
上記のクエリの出力には、以下に示すように、要求したフィールドが正確に含まれています。
{
"data": {
"students": [
{
"id": "S1001",
"firstName": "Mohtashim",
"lastName": "Mohammad",
"college": {
"name": "CUSAT",
"location": "Kerala"
}
},
{
"id": "S1002",
"firstName": "Kannan",
"lastName": "Sudhakaran",
"college": {
"name": "AMU",
"location": "Uttar Pradesh"
}
},
{
"id": "S1003",
"firstName": "Kiran",
"lastName": "Panigrahi",
"college": {
"name": "AMU",
"location": "Uttar Pradesh"
}
}
]
}
}
型システムで何が可能かを説明する
GraphQLは強く型付けされており、クエリはフィールドとそれに関連するデータ型に基づいています。GraphQLクエリに型の不一致がある場合、サーバーアプリケーションは明確で役立つエラーメッセージを返します。これは、クライアントアプリケーションによるスムーズなデバッグとバグの簡単な検出に役立ちます。GraphQLは、明示的なデータ変換と解析を減らすのに役立つクライアント側ライブラリーも提供します。
学生と大学のデータ型の例を以下に示します-
type Query {
students:[Student]
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
college:College
}
type College {
id:ID!
name:String
location:String
rating:Float
students:[Student]
}
強力な開発者ツールでより速く移動する
GraphQLは、ドキュメント化とクエリのテストのための豊富な開発者ツールを提供します。GraphiQLは、クエリとそのスキーマのドキュメントを生成する優れたツールです。また、クエリの構築中にGraphQLAPIとインテリジェントコード補完機能をテストするためのクエリエディターも提供します。
この章では、GraphQLの環境設定について学習します。このチュートリアルの例を実行するには、次のものが必要です。
Linux、macOS、またはWindowsを実行しているコンピューター。
ウェブブラウザ、できれば最新バージョンのGoogleChrome。
最近のバージョンのNode.jsがインストールされています。最新のLTSバージョンをお勧めします。
VSCode用の拡張機能GraphQLがインストールされたVisualStudioCodeまたは任意のコードエディター。
Nodejsを使用してGraphQLサーバーを構築する方法
以下に示すように、Nodejsを使用してGraphQLサーバーを構築するための詳細な段階的アプローチを実行します-
ステップ1-ノードとNpmのバージョンを確認する
NodeJをインストールした後、ターミナルで次のコマンドを使用して、nodeとnpmのバージョンを確認します-
C:\Users\Admin>node -v
v8.11.3
C:\Users\Admin>npm -v
5.6.0
ステップ2-プロジェクトフォルダを作成し、VSCodeで開きます
プロジェクトのルートフォルダーには、test-appという名前を付けることができます。
以下の手順を使用して、VisualStudioコードエディターを使用してフォルダーを開きます-
C:\Users\Admin>mkdir test-app
C:\Users\Admin>cd test-app
C:\Users\Admin\test-app>code.
ステップ3-package.jsonを作成し、依存関係をインストールします
GraphQLサーバーアプリケーションのすべての依存関係を含むpackage.jsonファイルを作成します。
{
"name": "hello-world-server",
"private": true,
"scripts": {
"start": "nodemon --ignore data/ server.js"
},
"dependencies": {
"apollo-server-express": "^1.4.0",
"body-parser": "^1.18.3",
"cors": "^2.8.4",
"express": "^4.16.3",
"graphql": "^0.13.2",
"graphql-tools": "^3.1.1"
},
"devDependencies": {
"nodemon": "1.17.1"
}
}
以下のコマンドを使用して依存関係をインストールします-
C:\Users\Admin\test-app>npm install
ステップ4-データフォルダにフラットファイルデータベースを作成する
このステップでは、フラットファイルを使用してデータを保存および取得します。フォルダデータを作成し、2つのファイルを追加しますstudents.json そして colleges.json。
以下は colleges.json ファイル-
[
{
"id": "col-101",
"name": "AMU",
"location": "Uttar Pradesh",
"rating":5.0
},
{
"id": "col-102",
"name": "CUSAT",
"location": "Kerala",
"rating":4.5
}
]
以下は students.json ファイル-
[
{
"id": "S1001",
"firstName":"Mohtashim",
"lastName":"Mohammad",
"email": "[email protected]",
"password": "pass123",
"collegeId": "col-102"
},
{
"id": "S1002",
"email": "[email protected]",
"firstName":"Kannan",
"lastName":"Sudhakaran",
"password": "pass123",
"collegeId": "col-101"
},
{
"id": "S1003",
"email": "[email protected]",
"firstName":"Kiran",
"lastName":"Panigrahi",
"password": "pass123",
"collegeId": "col-101"
}
]
ステップ5-データアクセス層を作成する
データフォルダの内容をロードするデータストアを作成する必要があります。この場合、コレクション変数、学生、大学が必要です。アプリケーションがデータを必要とするときはいつでも、これらのコレクション変数を利用します。
次のように、プロジェクトフォルダにファイルdb.jsを作成します-
const { DataStore } = require('notarealdb');
const store = new DataStore('./data');
module.exports = {
students:store.collection('students'),
colleges:store.collection('colleges')
};
ステップ6-スキーマファイルschema.graphqlを作成する
現在のプロジェクトフォルダにスキーマファイルを作成し、次の内容を追加します-
type Query {
test: String
}
ステップ7-リゾルバーファイルresolvers.jsを作成する
現在のプロジェクトフォルダにリゾルバファイルを作成し、次の内容を追加します-
const Query = {
test: () => 'Test Success, GraphQL server is up & running !!'
}
module.exports = {Query}
ステップ8-Server.jsを作成し、GraphQLを構成します
サーバーファイルを作成し、GraphQLを次のように構成します-
const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const db = require('./db');
const port = process.env.PORT || 9000;
const app = express();
const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})
app.use(cors(), bodyParser.json());
const {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
app.listen(
port, () => console.info(
`Server started on port ${port}`
)
);
ステップ9-アプリケーションを実行し、GraphiQLでテストする
プロジェクトtest-appのフォルダー構造を次のように確認します-
test-app /
-->package.json
-->db.js
-->data
students.json
colleges.json
-->resolvers.js
-->schema.graphql
-->server.js
以下のようにコマンドnpmstartを実行します-
C:\Users\Admin\test-app>npm start
サーバーは9000ポートで実行されているため、GraphiQLツールを使用してアプリケーションをテストできます。ブラウザを開き、URL http:// localhost:9000 / graphiqlを入力します。エディタに次のクエリを入力します-
{
Test
}
サーバーからの応答を以下に示します-
{
"data": {
"test": "Test Success, GraphQL server is running !!"
}
}
GraphQLは、GraphQLサーバーの動作を説明する仕様です。これは、サポートされているプロトコル、サーバーが受け入れることができるデータの形式、サーバーから返される応答の形式などのように、要求と応答を処理する方法に関する一連のガイドラインです。クライアントからGraphQLへの要求サーバーはクエリと呼ばれます。GraphQLのもう1つの重要な概念は、トランスポート層にとらわれないことです。TCP、WebSocket、その他のトランスポート層プロトコルなど、利用可能なネットワークプロトコルで使用できます。また、データベースに対して中立であるため、リレーショナルデータベースまたはNoSQLデータベースで使用できます。
GraphQL Serverは、以下の3つの方法のいずれかを使用してデプロイできます-
- データベースが接続されたGraphQLサーバー
- 既存のシステムを統合するGraphQLサーバー
- ハイブリッドアプローチ
接続されたデータベースを備えたGraphQLサーバー
このアーキテクチャには、統合データベースを備えたGraphQLサーバーがあり、多くの場合、新しいプロジェクトで使用できます。クエリを受信すると、サーバーはリクエストペイロードを読み取り、データベースからデータをフェッチします。これは、クエリの解決と呼ばれます。クライアントに返される応答は、公式のGraphQL仕様で指定された形式に準拠しています。
上の図では、GraphQLサーバーとデータベースが単一のノードに統合されています。クライアント(デスクトップ/モバイル)は、HTTPを介してGraphQLサーバーと通信します。サーバーはリクエストを処理し、データベースからデータをフェッチしてクライアントに返します。
既存のシステムを統合するGraphQLサーバー
このアプローチは、レガシーインフラストラクチャとさまざまなAPIを使用している企業に役立ちます。GraphQLを使用して、マイクロサービス、レガシーインフラストラクチャ、およびサードパーティのAPIを既存のシステムに統合できます。
上の図では、GraphQLAPIはクライアントと既存のシステム間のインターフェースとして機能します。クライアントアプリケーションはGraphQLサーバーと通信し、GraphQLサーバーはクエリを解決します。
ハイブリッドアプローチ
最後に、上記の2つのアプローチを組み合わせて、GraphQLサーバーを構築できます。このアーキテクチャーでは、GraphQLサーバーは受信したすべての要求を解決します。接続されたデータベースまたは統合APIからデータを取得します。これは下の図に表されています-
この章では、さまざまなGraphQLコンポーネントとそれらが相互に通信する方法について説明します。アプリケーションコンポーネント全体は、次のように区別できます。
- サーバー側コンポーネント
- クライアント側のコンポーネント
サーバー側コンポーネント
GraphQLサーバーは、サーバー側のコアコンポーネントを形成し、GraphQLクライアントアプリケーションからのクエリを解析できるようにします。Apollo Serverは、GraphQL仕様の最も一般的に使用される実装です。その他のサーバープログラミングコンポーネントには、次のものがあります。
シニア番号 | サーバーの要点と説明 |
---|---|
1 | Schema GraphQLスキーマは、GraphQLサーバーの実装の中心であり、それに接続するクライアントが利用できる機能を記述します。 |
2 | Query GraphQLクエリは、データベースまたはレガシーAPIからデータを取得するためのクライアントアプリケーションリクエストです。 |
3 | Resolver リゾルバーは、GraphQL操作をデータに変換するための指示を提供します。リゾルバー関数を定義することにより、クエリをデータに解決します。 |
クライアント側のコンポーネント
以下にクライアント側のコンポーネントを示します-
シニア番号 | ツールと説明 |
---|---|
1 | GraphiQL GraphQLクエリとミューテーションを編集およびテストするためのブラウザベースのインターフェイス。 |
2 | ApolloClient GraphQLクライアントアプリケーションを構築するための最良のツール。すべてのJavaScriptフロントエンドとうまく統合します。 |
次の図は、 Client-Server architecture。Webサーバーは、NodeJとExpressフレームワーク上に構築されています。ReactJSアプリケーション(Apolloクライアントライブラリを使用して構築)またはGraphiQLブラウザアプリケーションによってApolloGraphQLサーバーにリクエストが行われます。クエリは解析され、サーバーで定義されたスキーマに対して検証されます。リクエストスキーマが検証に合格すると、関連するリゾルバー関数が実行されます。リゾルバーには、APIまたはデータベースからデータをフェッチするためのコードが含まれます。
この章では、挨拶メッセージHelloWorldを返す単純なAPIを作成し、GraphiQLを使用してそれにアクセスします。
例
この例は、NodeJS、Express、およびApolloサーバーに基づいています。次の手順ですべての概念をまとめることを学びます-
ステップ1-Expressの設定
ExpressJSは、WebサイトおよびWebアプリケーションの構築を支援するWebアプリケーションフレームワークです。この例では、Expressフレームワークの上にGraphQLAPIを構築します。
次のステップはフォルダを作成することです hello-world-serverターミナルから同じフォルダに移動します。package.jsonを追加し、パッケージに名前を付けます。このパッケージは内部でのみ使用されるため、プライベートとして宣言できます。
{
"name":"hello-world-server",
"private":true
}
以下に示すように、Expressサーバーの依存関係をインストールします-
C:\Users\Admin\hello-world-server>npm install express body-parser cors
body-parserは、ExpressがHTTPPostリクエストを効率的に処理するのに役立つミドルウェアパッケージです。corsは、オリジン間リソース共有を処理するもう1つのミドルウェアパッケージです。
作成する server.js プロジェクトフォルダ内のファイルに次のように入力します-
const bodyParser = require('body-parser')
const cors = require('cors')
const express = require('express')
const port = process.env.PORT|| 9000
const app = express()
//register middleware
app.use(bodyParser.json() , cors())
app.listen(port, () => console.log(`server is up and running at ${port}`)
Expressサーバーが稼働しているかどうかを確認するには、ターミナルウィンドウで次のコードを実行します-
C:\Users\Admin\hello-world-server>node server.js
次の出力がサーバーコンソールに表示されます。これは、Expressサーバーがポート9000で実行されていることを示しています。
server is up and running at 9000
ブラウザを開いて入力すると http://localhost:9000、次の画面が表示されます-
サーバーを停止するには、を押します Ctrl + C。
ステップ2-GraphQLとApolloサーバーをインストールする
Expressが構成されたので、次のステップは次のGraphQL依存関係をダウンロードすることです-
- graphql
- graphql-tools
- apollo-server-express@1
安定版リリースであるApolloサーバーv1.0を使用します。次のコマンドを入力して、これらの依存関係をインストールします-
C:\Users\Admin\hello-world-server>npm install graphql graphql-tools apollo-server-express@1
これらの依存関係が正常にインストールされているかどうかを確認するには、 package.json 以前に作成したファイル。
{
"name": "hello-world-server",
"private": true,
"dependencies": {
"apollo-server-express": "^1.4.0",
"body-parser": "^1.18.3",
"cors": "^2.8.4",
"express": "^4.16.3",
"graphql": "^0.13.2",
"graphql-tools": "^3.1.1"
}
}
ステップ3-スキーマを定義する
GraphQLスキーマは、サービスからフェッチできるオブジェクトの種類と、サービスに含まれるフィールドを定義します。スキーマは、を使用して定義できますGraphQL Schema Definition Language。次に、次のコードスニペットをserver.js ファイル-
// Adding Type Definitions
const typeDefinition = `
type Query {
greeting: String
}
ここで、クエリには文字列値を返す挨拶属性が含まれています。
ステップ4-リゾルバーを作成する
リゾルバーを作成する最初のステップは、グリーティングフィールドのリクエストを処理するコードを追加することです。これはで指定されていますresolver。リゾルバー関数の構造はスキーマと一致する必要があります。次のコードスニペットをに追加しますserver.js ファイル。
// Adding resolver
const resolverObject = {
Query : {
greeting: () => 'Hello GraphQL From TutorialsPoint !!'
}
}
2番目のステップは、を使用してスキーマとリゾルバーをバインドすることです。 makeExecutableSchema。この関数は、graphql-toolsモジュールで事前定義されています。次のコードスニペットをに追加します server.js ファイル。
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs:typeDefinition, resolvers:resolverObject})
ステップ5-ReactJS / GraphiQLアプリケーションからデータをフェッチするためのルートを定義する
次のコードスニペットをに追加します server.js ファイル-
const {graphqlExpress, graphiqlExpress} = require('apollo-server-express')
//create routes for graphql and graphiql
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
graphqlExpressの機能は、ルートを登録することができますhttp://localhost:9000/graphql。ReactJSアプリケーションは、このエンドポイントを使用してデータをクエリできます。同様に、graphqliExpress関数はルートの登録に役立ちますhttp://localhost:9000/graphiql。これは、APIをテストするためにGraphiQLブラウザークライアントによって使用されます。
完全なserver.jsコードは次のとおりです-
const bodyParser = require('body-parser')
const cors = require('cors')
const express = require('express')
const port = process.env.PORT||9000
const app = express()
app.use(bodyParser.json() , cors())
const typeDefinition = `
type Query {
greeting: String
}`
const resolverObject = {
Query : {
greeting: () => 'Hello GraphQL From TutorialsPoint !!'
}
}
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs:typeDefinition, resolvers:resolverObject})
const {graphqlExpress,graphiqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
app.listen(port, () => console.log(`server is up and running ${port}`))
ステップ6-アプリケーションを起動します
実行する server.js Node.jsを次のように使用する-
C:\Users\Admin\hello-world-server>node server.js
ステップ7-GraphQLAPIをテストする
ブラウザを開いて入力します http://localhost:9000/graphiql。GraphiQLのクエリタブで、次のように入力します-
{
greeting
}
サーバーからの応答を以下に示します-
{
"data": {
"greeting": "Hello GraphQL From TutorialsPoint !!"
}
}
次の画像は応答を示しています-
Note − ApolloServerバージョン1.0が使用されていることを確認してください。
GraphQLは強く型付けされた言語です。型システムは、GraphQLアプリケーションで使用できるさまざまなデータ型を定義します。型システムは、クライアントとサーバー間のコントラクトであるスキーマを定義するのに役立ちます。一般的に使用されるGraphQLデータ型は次のとおりです-
シニア番号 | タイプと説明 |
---|---|
1 | Scalar 単一の値を格納します |
2 | Object フェッチできるオブジェクトの種類を示します |
3 | Query 他の特定のタイプへのエントリポイントタイプ |
4 | Mutation データ操作のエントリポイント |
5 | Enum ユーザーが所定のオプションリストから選択する必要がある状況で役立ちます |
スカラータイプ
スカラー型は、単一の値のみを格納できるプリミティブデータ型です。GraphQLが提供するデフォルトのスカラータイプは-です。
Int −符号付き32ビット整数
Float −符号付き倍精度浮動小数点値
String −UTF-8文字のシーケンス
Boolean −正誤問題
ID −一意の識別子。多くの場合、オブジェクトをフェッチするための一意の識別子として、またはキャッシュのキーとして使用されます。
スカラー型を定義するための構文は次のとおりです。
field: data_type
以下のスニペットは、文字列値を返すgreetingという名前のフィールドを定義しています。
greeting: String
オブジェクトタイプ
オブジェクトタイプは、スキーマで使用される最も一般的なタイプであり、フィールドのグループを表します。オブジェクトタイプ内の各フィールドは別のタイプにマップされるため、ネストされたタイプが可能になります。つまり、オブジェクトタイプは、複数のスカラータイプまたはオブジェクトタイプで構成されます。
オブジェクトタイプを定義するための構文を以下に示します-
type object_type_name
{
field1: data_type
field2:data_type
....
fieldn:data_type
}
次のコードスニペットを検討できます-
--Define an object type--
type Student {
stud_id:ID
firstname: String
age: Int
score:Float
}
--Defining a GraphQL schema--
type Query
{
stud_details:[Student]
}
上記の例では、オブジェクトデータ型Studentを定義しています。ルートクエリスキーマのstud_detailsフィールドは、Studentオブジェクトのリストを返します。
クエリタイプ
GraphQLクエリは、データをフェッチするために使用されます。これは、RESTベースのAPIでリソースをリクエストするようなものです。簡単にするために、クエリタイプはクライアントアプリケーションからGraphQLサーバーに送信されるリクエストです。GraphQLはSchema Definition Language (SDL)クエリを定義します。クエリタイプは、GraphQLの多くのルートレベルタイプの1つです。
クエリを定義するための構文は次のとおりです-
type Query {
field1: data_type
field2:data_type
field2(param1:data_type,param2:data_type,...paramN:data_type):data_type
}
クエリの定義例-
type Query {
greeting: String
}
突然変異の種類
ミューテーションは、サーバーに送信される操作です。 create, update または deleteデータ。これらは、RESTベースのAPIを呼び出すためのPUT、POST、PATCH、およびDELETE動詞に類似しています。
ミューテーションは、GraphQLのルートレベルのデータ型の1つです。クエリタイプはデータフェッチ操作のエントリポイントを定義し、ミューテーションタイプはデータ操作操作のエントリポイントを指定します。
ミューテーションタイプを定義するための構文を以下に示します-
type Mutation {
field1: data_type
field2(param1:data_type,param2:data_type,...paramN:data_type):data_type
}
たとえば、ミューテーションタイプを定義して、次のように新しいStudentを追加できます。
type Mutation {
addStudent(firstName: String, lastName: String): Student
}
列挙型
列挙型はスカラー型に似ています。列挙型は、フィールドの値がオプションの指定されたリストからのものでなければならない状況で役立ちます。
列挙型を定義するための構文は次のとおりです。
type enum_name{
value1
value2
}
次のスニペットは、列挙型を定義する方法を示しています-
type Days_of_Week{
SUNDAY
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
}
リストタイプ
リストは、特定のタイプの値の配列を表すために使用できます。リストは、オブジェクトタイプ、スカラー、および列挙型をラップするタイプ修飾子[]で定義されます。
次の構文を使用して、リストタイプを定義できます-
field:[data_type]
以下の例では、リストタイプのtodosを定義しています-
type Query {
todos: [String]
}
null許容型
デフォルトでは、各コアスカラータイプをnullに設定できます。つまり、これらの型は、指定された型の値を返すことも、値を持たないこともできます。このデフォルトをオーバーライドし、フィールドを定義する必要があることを指定するには、感嘆符(!)をタイプに追加できます。これにより、クエリによって返される結果に値が確実に含まれるようになります。
次の構文を使用して、NULL不可のフィールドを定義できます-
field:data_type!
以下の例では、stud_idが必須フィールドとして宣言されています。
type Student {
stud_id:ID!
firstName:String
lastName:String
fullName:String
college:College
}
GraphQLスキーマは、GraphQLサーバー実装の中核です。接続するクライアントアプリケーションで使用できる機能について説明します。任意のプログラミング言語を使用して、GraphQLスキーマを作成し、その周りにインターフェースを構築できます。
GraphQLランタイムは、それが表すデータサービスの機能を公開するための一般的なグラフベースのスキーマを定義します。クライアントアプリケーションは、その機能内でスキーマをクエリできます。このアプローチにより、クライアントがサーバーから切り離され、独立して進化と拡張の両方が可能になります。
この章では、Apolloサーバーを使用してGraphQLクエリを実行します。ザ・makeExecutableSchema graphql-toolsの関数は、スキーマとリゾルバーをバインドするのに役立ちます。
makeExecutableSchema関数の構文
ザ・ makeExecutableSchema関数は、オブジェクト型の単一の引数{}を取ります。この関数を使用するための構文を以下に示します-
import { makeExecutableSchema } from 'graphql-tools';
const jsSchema = makeExecutableSchema({
typeDefs,
resolvers, // optional
logger, // optional
allowUndefinedInResolve = false, // optional
resolverValidationOptions = {}, // optional
directiveResolvers = null, // optional
schemaDirectives = null, // optional
parseOptions = {}, // optional
inheritResolversFromInterfaces = false // optional
});
シニア番号 | パラメータと説明 |
---|---|
1 | typeDefs これは必須の引数です。GraphQLクエリをUTF-8文字列として表します。 |
2 | Resolvers これはオプションの引数です(デフォルトでは空のオブジェクト)。これには、クエリを処理する関数があります。 |
3 | logger これはオプションの引数であり、サーバーコンソールにエラーを出力するために使用できます。 |
4 | parseOptions これはオプションの引数であり、typeDefsを文字列として指定するときに解析をカスタマイズできます。 |
5 | allowUndefinedInResolve これはデフォルトで当てはまります。falseに設定すると、resolve関数がundefinedを返す場合にエラーをスローします。 |
6 | resolverValidationOptions これはオプションの引数であり、ブールプロパティを持つオブジェクトを受け入れます。 |
7 | inheritResolversFromInterfaces これはオプションの引数であり、ブール引数を受け入れてリゾルバーオブジェクトの継承をチェックします。 |
図
このスキーマを理解するための簡単なアプリケーションを作成しましょう。これにより、サーバーから学生のリストを照会するためのスキーマが作成されます。学生データはフラットファイルに保存され、次のノードモジュールを使用します。notarealdb データベースを偽造し、フラットファイルから読み取ります。
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
名前の付いたフォルダを作成します schema-app。ターミナルからディレクトリをschema-appに変更します。次に、「環境設定」の章で説明されている手順3〜5に従って、ダウンロードとインストールのプロセスを完了します。
ステップ2-スキーマを作成する
追加 schema.graphql プロジェクトフォルダ内のファイル、 schema-app 次のコードを追加します-
type Query {
greeting:String
students:[Student]
}
type Student {
id:ID!
firstName:String
lastName:String
password:String
collegeId:String
}
スキーマのルートはクエリタイプになります。クエリには、文字列と学生のリストをそれぞれ返す挨拶と学生の2つのフィールドがあります。Studentは複数のフィールドを含むため、オブジェクトタイプとして宣言されます。IDフィールドはNULL不可として宣言されています。
ステップ3-リゾルバーを作成する
ファイルを作成する resolvers.js プロジェクトフォルダに次のコードを追加します-
const db = require('./db')
const Query = {
greeting:() => {
return "hello from TutorialsPoint !!!"
},
students:() => db.students.list()
}
module.exports = {Query}
ここでは、挨拶と学生がクエリを処理するリゾルバーです。 students resolver functionデータアクセス層から学生のリストを返します。モジュール外のリゾルバー関数にアクセスするには、Queryオブジェクトを使用してエクスポートする必要がありますmodule.exports。
ステップ4-アプリケーションを実行する
server.jsファイルを作成し、環境設定の章の手順8を参照してください。次のステップは、ターミナルでコマンドnpmstartを実行することです。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。ブラウザを開いてURLを入力し、http://localhost:9000/graphiql。
エディタに次のクエリを入力します-
{
greeting
students {
id
firstName
lastName
}
}
クエリは次のように出力を表示します-
Note−students.jsonをRESTfulAPI呼び出しに置き換えて、学生データ、またはMySQLやMongoDBなどの実際のデータベースを取得できます。GraphQLは、パフォーマンスを向上させるために、元のアプリケーション層の薄いラッパーになります。
Resolverは、GraphQLクエリの応答を生成する関数のコレクションです。簡単に言うと、リゾルバーはGraphQLクエリハンドラーとして機能します。GraphQLスキーマのすべてのリゾルバー関数は、以下に示す4つの位置引数を受け入れます-
fieldName:(root, args, context, info) => { result }
リゾルバ関数の例を以下に示します-
//resolver function with no parameters and returning string
greeting:() => {
return "hello from TutorialsPoint !!!"
}
//resolver function with no parameters and returning list
students:() => db.students.list()
//resolver function with arguments and returning object
studentById:(root,args,context,info) => {
return db.students.get(args.id);
}
以下に、位置引数とその説明を示します-
シニア番号 | 引数と説明 |
---|---|
1 | root 親フィールドのリゾルバーから返された結果を含むオブジェクト。 |
2 | args クエリのフィールドに渡された引数を持つオブジェクト。 |
3 | context これは、特定のクエリですべてのリゾルバーによって共有されるオブジェクトです。 |
4 | info これには、フィールド名、ルートからフィールドへのパスなど、クエリの実行状態に関する情報が含まれています。 |
リゾルバ結果フォーマット
GraphQLのリゾルバーは、以下に示すようにさまざまなタイプの値を返すことができます。
シニア番号 | 引数と説明 |
---|---|
1 | null or undefined これは、オブジェクトが見つからなかったことを示します |
2 | array これは、フィールドの結果がリストである必要があることをスキーマが示している場合にのみ有効です。 |
3 | promise リゾルバーは、データベースやバックエンドAPIからのフェッチなどの非同期アクションを実行することが多いため、promiseを返すことができます。 |
4 | scalar or object リゾルバーは他の値を返すこともできます |
図
リゾルバーを理解するための簡単なアプリケーションを作成しましょう。これにより、サーバーからIDで学生にクエリを実行するためのスキーマが作成されます。学生データはフラットファイルに保存され、次のノードモジュールを使用します。notarealdb データベースを偽造し、フラットファイルから読み取ります。
以下は、簡単なアプリケーションを作成するための段階的なプロセスです。
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
名前の付いたフォルダを作成します resolver-app。ディレクトリを次のように変更しますresolver-appターミナルから。後で、環境設定の章の手順3〜5に従います。
ステップ2-スキーマを作成する
プロジェクトフォルダーresolver-appにschema.graphqlファイルを追加し、次のコードを追加します-
type Query {
greeting:String
students:[Student]
studentById(id:ID!):Student
}
type Student {
id:ID!
firstName:String
lastName:String
password:String
collegeId:String
}
スキーマファイルは、ユーザーが挨拶、学生、studentByIdをクエリできることを示しています。特定のIDを持つ学生を取得するには、data type ID!これは、NULL不可の一意の識別子フィールドを示しています。学生のフィールドには、学生の配列を返し、挨拶返します単純な文字列値を。
ステップ3-リゾルバーを作成する
ファイルを作成する resolvers.js プロジェクトフォルダに次のコードを追加します-
const db = require('./db')
const Query = {
//resolver function for greeting
greeting:() => {
return "hello from TutorialsPoint !!!"
},
//resolver function for students returns list
students:() => db.students.list(),
//resolver function for studentbyId
studentById:(root,args,context,info) => {
//args will contain parameter passed in query
return db.students.get(args.id);
}
}
module.exports = {Query}
ここで、studentByIdは3つのパラメーターを取ります。この章で説明するように、studentIdはargsから取得できます。rootには、Queryオブジェクト自体が含まれます。特定の学生を返すには、studentsコレクションのidパラメーターを指定してgetメソッドを呼び出す必要があります。
ここで、greeting、students、studentByIdは、クエリを処理するリゾルバーです。students resolver functionデータアクセス層から学生のリストを返します。モジュール外のリゾルバー関数にアクセスするには、module.exportsを使用してQueryオブジェクトをエクスポートする必要があります。
ステップ4-アプリケーションを実行する
server.jsファイルを作成します。環境設定の章のステップ8を参照してください。ターミナルでコマンドnpmstartを実行します。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
ブラウザを開いてURLを入力し、 http://localhost:9000/graphiql。エディタに次のクエリを入力します-
{
studentById(id:"S1001") {
id
firstName
lastName
}
}
上記のクエリの出力は次のとおりです-
{
"data": {
"studentById": {
"id": "S1001",
"firstName": "Mohtashim",
"lastName": "Mohammad"
}
}
}
GraphQL操作は、読み取り操作または書き込み操作のいずれかです。GraphQLクエリは値の読み取りまたはフェッチに使用され、ミューテーションは値の書き込みまたは投稿に使用されます。いずれの場合も、操作はGraphQLサーバーが解析し、特定の形式のデータで応答できる単純な文字列です。モバイルおよびWebアプリケーションで通常使用される一般的な応答形式はJSONです。
クエリを定義する構文は次のとおりです-
//syntax 1
query query_name{ someField }
//syntax 2
{ someField }
以下はクエリの例です-
//query with name myQuery
query myQuery{
greeting
}
// query without any name
{
greeting
}
上記の例から、queryキーワードがオプションであることは明らかです。
GraphQLクエリは、データのオーバーフェッチを減らすのに役立ちます。Restful APIとは異なり、GraphQLを使用すると、ユーザーはサーバーからフェッチする必要のあるフィールドを制限できます。これは、クエリが小さくなり、ネットワーク上のトラフィックが少なくなることを意味します。これにより、応答時間が短縮されます。
図1-カスタムフィールドを使用した学生モデルのクエリ
この例では、jsonファイルに保存されている学生のセットがあります。各学生モデルには、firstName、lastName、idなどのフィールドがありますが、fullNameはありません。ここでは、すべての学生のfullNameを取得するクエリを作成する方法について説明します。このために、両方のスキーマリゾルバーでfullNameフィールドを作成する必要があります。
以下の手順を使用して、この図を作成する方法を見てみましょう。
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
名前の付いたフォルダを作成します query-app。ディレクトリを次のように変更しますquery-appターミナルから。後で、環境設定の章で説明されている手順3〜5に従います。
ステップ2-スキーマを作成する
追加 schema.graphql プロジェクトフォルダquery-appにファイルし、次のコードを追加します-
type Query {
greeting:String
students:[Student]
studentById(id:ID!):Student
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
}
にはfullNameフィールドがないことに注意してくださいstudents.jsonファイル。ただし、クエリを介して学生のフルネームを取得する必要があります。fullNameが、この場合には、データ・ソースでは使用できませんカスタムフィールドになります。
ステップ3-リゾルバーを作成する
ファイルを作成する resolvers.js プロジェクトフォルダに次のコードを追加します-
const db = require('./db')
const Query = {
//resolver function for greeting
greeting:() => {
return "hello from TutorialsPoint !!!"
},
//resolver function for students returns list
students:() => db.students.list(),
//resolver function for studentbyId
studentById:(root,args,context,info) => {
//args will contain parameter passed in query
return db.students.get(args.id);
}
}
//for each single student object returned,resolver is invoked
const Student = {
fullName:(root,args,context,info) => {
return root.firstName+":"+root.lastName
}
}
module.exports = {Query,Student}
ステップ4-アプリケーションを実行する
作成する server.jsファイル。環境設定の章のステップ8を参照してください。ターミナルでコマンドnpmstartを実行し ます。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
ブラウザを開き、URLを入力します http://localhost:9000/graphiql。エディタに次のクエリを入力します-
{
students{
id
fullName
}
}
クエリに対する応答を以下に示します-
{
"data": {
"students": [
{
"id": "S1001",
"fullName": "Mohtashim:Mohammad"
},
{
"id": "S1002",
"fullName": "Kannan:Sudhakaran"
},
{
"id": "S1003",
"fullName": "Kiran:Panigrahi"
}
]
}
}
作成する server.js 次のコードを追加します-
const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const db = require('./db');
const port = 9000;
const app = express();
//loading type definitions from schema file
const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
//loading resolvers
const resolvers = require('./resolvers')
//binding schema and resolver
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})
//enabling cross domain calls and form post
app.use(cors(), bodyParser.json());
//enabling routes
const {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
//registering port
app.listen(port, () => console.info(`Server started on port ${port}`));
ターミナルでコマンドnpmstartを実行します。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
ブラウザを開き、URLを入力します http://localhost:9000/graphiql。エディタに次のクエリを入力します-
{
students{
id
fullName
}
}
クエリに対する応答を以下に示します-
{
"data": {
"students": [
{
"id": "S1001",
"fullName": "Mohtashim:Mohammad"
},
{
"id": "S1002",
"fullName": "Kannan:Sudhakaran"
},
{
"id": "S1003",
"fullName": "Kiran:Panigrahi"
}
]
}
}
図2-ネストされたクエリ
学生の詳細と大学の詳細を取得するためのネストされたクエリを作成しましょう。同じプロジェクトフォルダで作業します。
ステップ1-スキーマを編集する
スキーマファイルにはすでにstudentフィールドがあります。フィールドカレッジを追加して、そのタイプを定義しましょう。
type College {
id:ID!
name:String
location:String
rating:Float
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
college:College
}
ステップ2-resolver.jsを変更します
以下のように大学のレゾルバ関数を追加する必要があります。大学のリゾルバ関数は、返された各学生オブジェクトに対して実行されます。この場合のresolverのrootパラメーターにはstudentが含まれます。
const Student = {
fullName:(root,args,context,info) => {
return root.firstName+":"+root.lastName
},
college:(root) => {
return db.colleges.get(root.collegeId);
}
}
module.exports = {Query,Student}
リゾルバーは、collegeコレクションのgetメソッドを呼び出し、collegeIdを渡すことにより、各学生の大学を返します。私たちはcollegeIdを通じてStudentとCollegeの間に関連関係があります。
ステップ3-アプリケーションをテストする
ターミナルウィンドウを開き、プロジェクトフォルダに移動します。コマンド-npmstartを入力します。ブラウザを起動し、URLを入力しますhttp://localhost:9000/graphiql。
GraphiQLウィンドウに次のクエリを入力します-
{
students{
id
firstName
college {
id
name
location
rating
}
}
}
クエリに対する応答は次のとおりです-
{
"data": {
"students": [
{
"id": "S1001",
"firstName": "Mohtashim",
"college": {
"id": "col-102",
"name": "CUSAT",
"location": "Kerala",
"rating": 4.5
}
},
{
"id": "S1002",
"firstName": "Kannan",
"college": {
"id": "col-101",
"name": "AMU",
"location": "Uttar Pradesh",
"rating": 5
}
},
{
"id": "S1003",
"firstName": "Kiran",
"college": {
"id": "col-101",
"name": "AMU",
"location": "Uttar Pradesh",
"rating": 5
}
}
]
}
}
クエリ変数とは何ですか?
クエリに渡される動的な値がある場合は、変数を使用してこれらの動的な値を表します。したがって、クエリはクライアントアプリケーションで再利用できます。
図
クエリ変数を理解するための簡単なアプリケーションを作成しましょう。
ステップ1-スキーマファイルを編集する
文字列パラメータを受け取り、文字列を返すsayHelloフィールドを追加します。名前の値は、クライアントアプリケーションで動的になります。
type Query {
sayHello(name:String!):String
}
ステップ2-resolver.jsファイルを編集する
以下のパラメータをとるsayHelloリゾルバを追加します-
sayHello:(root,args,context,info) => `Hi ${args.name} GraphQL server says Hello to you!!`
ステップ3-GraphiQLでクエリ変数を宣言する
変数は、$とそれに続く変数名で宣言されます。例:$ myname_Variable。
$ myname_Variableが宣言されたら、名前付きクエリ構文で使用する必要があります。クエリmyQueryは文字列値を受け取り、以下に示すようにそれをsayHelloに渡します-
query myQuery($myname_Variable:String!) { sayHello(name:$myname_Variable)
}
GraphiQLクライアントの[クエリ変数]セクションで、$ myname_Variableの値をJSONオブジェクトとして設定します。
{
"myname_Variable": "Mohtashim"
}
上記のコードの出力は次のとおりです-
{
"data": {
"sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
}
}
列挙型でクエリ変数を使用する方法
フィールドパラメータがであるときにクエリ変数を使用する方法を見てみましょう enum type。
ステップ1-schema.graphqlファイルを編集する
enum ColorType {
RED
BLUE
GREEN
}
type Query {
setFavouriteColor(color:ColorType):String
}
setFavouriteColorの関数は、入力として列挙を受け取り、文字列値を返します。
ステップ2-resolvers.jsファイルを編集する
リゾルバー関数setFavouriteColorはrootとargsを取ります。実行時に関数に渡される列挙値には、argsパラメーターを介してアクセスできます。
setFavouriteColor:(root,args) => {
return "Your Fav Color is :"+args.color;
}
ステップ3-GraphiQLでクエリ変数を宣言する
クエリの名前は query_to_setColorこれは、ColorTypeのcolor_variableという名前の変数を取ります。この変数はメソッドsetFavouriteColorに渡されます。
query query_to_setColor($color_variable:ColorType) {
setFavouriteColor(color:$color_variable)
}
GraphiQLのクエリ変数セクションに、次のコードを入力します-
{
"color_variable":"RED"
}
応答を以下に示します-
{
"data": {
"setFavouriteColor": "Your Fav Color is: RED"
}
}
この章では、GraphQLでのミューテーションクエリについて学習します。
ミューテーションクエリは、データストア内のデータを変更し、値を返します。データの挿入、更新、または削除に使用できます。突然変異はスキーマの一部として定義されます。
ミューテーションクエリの構文を以下に示します-
mutation{
someEditOperation(dataField:"valueOfField"):returnType
}
図
ミューテーションクエリを使用して、新しい学生レコードをデータストアに追加する方法を理解しましょう。
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
mutation-appという名前でプロジェクトフォルダーを作成します。ターミナルからディレクトリをmutation-appに変更します。環境設定の章で説明されている手順3〜5に従います。
ステップ2-schema.graphqlファイルを作成する
追加 schema.graphql プロジェクトフォルダmutation-appにファイルし、次のコードを追加します-
type Query {
greeting:String
}
type Mutation {
createStudent(collegeId:ID,firstName:String,lastName:String):String
}
関数createStudentは文字列型を返すことに注意してください。これは、学生の作成後に生成される一意の識別子(ID)です。
ステップ3-resolver.jsファイルを作成する
プロジェクトフォルダにファイルresolvers.jsを作成し、次のコードを追加します-
const db = require('./db')
const Mutation = {
createStudent:(root,args,context,info) => {
return db.students.create({collegeId:args.collegeId,
firstName:args.firstName,
lastName:args.lastName})
}
}
const Query = {
greeting:() => "hello"
}
module.exports = {Query,Mutation}
ミューテーション関数は、データストア内の学生コレクションを指します。新しい学生を追加するには、studentsコレクションでcreateメソッドを呼び出します。引数のオブジェクトがクエリに渡されるパラメータが含まれています。学生コレクションのcreateメソッドは、新しく作成された学生オブジェクトのIDを返します。
ステップ4-アプリケーションを実行する
作成する server.jsファイル。環境設定の章のステップ8を参照してください。ターミナルでコマンドnpmstartを実行します。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
次のステップは、ブラウザを開いてURLを入力することです http://localhost:9000/graphiql。エディタに次のクエリを入力します-
//college Id should be matched with data from colleges.json for easy retrieval
mutation {
createStudent(collegeId:"col-2",firstName:"Tim",lastName:"George")
}
上記のクエリは、student.jsonファイルにstudentオブジェクトを作成します。クエリは一意の識別子を返します。クエリの応答は次のとおりです-
{
"data": {
"createStudent": "SkQtxYBUm"
}
}
Studentオブジェクトが作成されているかどうかを確認するには、studentByIdクエリを使用できます。データフォルダーからstudents.jsonファイルを開いてIDを確認することもできます。
studentByIdクエリを使用するには、 schema.graphql 以下に示すように-
type Query {
studentById(id:ID!):Student
}
type Student {
id:ID!
firstName:String
lastName:String
collegeId:String
}
編集する resolver.js 以下に示すファイル-
const db = require('./db')
const Query = {
studentById:(root,args,context,info) => {
return db.students.get(args.id);
}
}
const Mutation = {
createStudent:(root,args,context,info) => {
return db.students.create({collegeId:args.collegeId,
firstName:args.firstName,
lastName:args.lastName})
}
}
module.exports = {Query,Mutation}
以下に示すのは、ミューテーションクエリから返された一意のIDで学生を取得するためのクエリです。
{
studentById(id:"SkQtxYBUm") {
id
firstName
lastName
}
}
サーバーからの応答は次のとおりです-
{
"data": {
"studentById": {
"id": "SkQtxYBUm",
"firstName": "Tim",
"lastName":"George"
}
}
}
ミューテーションでオブジェクトを返す
オブジェクトを変更して返すことをお勧めします。たとえば、クライアントアプリケーションは、学生と大学の詳細を取得したいと考えています。この場合、2つの異なるリクエストを行うのではなく、学生とその大学の詳細を含むオブジェクトを返すクエリを作成できます。
ステップ1-スキーマファイルを編集する
名前の付いた新しいメソッドを追加します addStudent の突然変異タイプでオブジェクトを返します schema.graphql。
学生の詳細から大学の詳細にアクセスする方法を学びましょう。スキーマファイルに大学タイプを追加します。
type Mutation {
addStudent_returns_object(collegeId:ID,firstName:String,lastName:String):Student
createStudent(collegeId:ID,firstName:String,lastName:String):String
}
type College {
id:ID!
name:String
location:String
rating:Float
}
type Student {
id:ID!
firstName:String
lastName:String
college:College
}
ステップ2-resolvers.jsファイルを更新します
ファイルを更新する resolvers.js プロジェクトフォルダに次のコードを追加します-
const Mutation = {
createStudent:(root,args,context,info) => {
return db.students.create({
collegeId:args.collegeId,
firstName:args.firstName,
lastName:args.lastName
})
},
// new resolver function
addStudent_returns_object:(root,args,context,info) => {
const id = db.students.create({
collegeId:args.collegeId,
firstName:args.firstName,
lastName:args.lastName
})
return db.students.get(id)
}
}
//for each single student object returned,resolver is invoked
const Student = {
college:(root) => {
return db.colleges.get(root.collegeId);
}
}
module.exports = {Query,Student,Mutation}
ステップ3-サーバーを起動し、GraphiQLにリクエストクエリを入力します
次に、サーバーを起動し、次のコードを使用してGraphiQLでクエリを要求します-
mutation {
addStudent_returns_object(collegeId:"col-101",firstName:"Susan",lastName:"George") {
id
firstName
college{
id
name
}
}
}
上記のクエリは、新しい学生を追加し、大学のオブジェクトとともに学生のオブジェクトを取得します。これにより、サーバーへのラウンドトリップが節約されます。
応答は以下のとおりです-
{
"data": {
"addStudent_returns_object": {
"id": "rklUl08IX",
"firstName": "Susan",
"college": {
"id": "col-101",
"name": "AMU"
}
}
}
}
データを追加または変更するときは、ユーザー入力を検証することが重要です。たとえば、フィールドの値が常にnullではないことを確認する必要がある場合があります。使用できます! (non-nullable) GraphQLにマーカーを入力して、このような検証を実行します。
を使用するための構文 ! タイプマーカーは以下のとおりです-
type TypeName {
field1:String!,
field2:String!,
field3:Int!
}
上記の構文により、すべてのフィールドがnullにならないことが保証されます。
文字列の長さのチェックや数値が特定の範囲内にあるかどうかのチェックなどの追加のルールを実装する場合は、カスタムバリデーターを定義できます。カスタム検証ロジックは、リゾルバー関数の一部になります。例を使ってこれを理解しましょう。
イラスト-カスタムバリデーターの実装
基本的な検証を含むサインアップフォームを作成しましょう。フォームには、電子メール、名、パスワードのフィールドがあります。
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
名前の付いたフォルダを作成します validation-app。ターミナルからディレクトリをvalidation-appに変更します。環境設定の章で説明されている手順3〜5に従います。
ステップ2-スキーマを作成する
追加 schema.graphql プロジェクトフォルダ内のファイル validation-app 次のコードを追加します-
type Query {
greeting:String
}
type Mutation {
signUp(input:SignUpInput):String
}
input SignUpInput {
email:String!,
password:String!,
firstName:String!
}
Note−入力タイプSignUpInputを使用して、signUp関数のパラメーターの数を減らすことができます。したがって、signUp関数はSignUpInputタイプのパラメーターを1つだけ取ります。
ステップ3-リゾルバを作成する
ファイルを作成する resolvers.js プロジェクトフォルダに次のコードを追加します-
const Query = {
greeting:() => "Hello"
}
const Mutation ={
signUp:(root,args,context,info) => {
const {email,firstName,password} = args.input;
const emailExpression = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const isValidEmail = emailExpression.test(String(email).toLowerCase())
if(!isValidEmail)
throw new Error("email not in proper format")
if(firstName.length > 15)
throw new Error("firstName should be less than 15 characters")
if(password.length < 8 )
throw new Error("password should be minimum 8 characters")
return "success";
}
}
module.exports = {Query,Mutation}
リゾルバー関数であるsignUpは、パラメーターemail、password、およびfirstNameを受け入れます。これらは入力変数を介して渡されるため、args.inputを介してアクセスできます。
ステップ4-アプリケーションを実行する
server.jsファイルを作成します。環境設定の章のステップ8を参照してください。ターミナルでコマンドnpmstartを実行します。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
ブラウザを開き、URLを入力します http://localhost:9000/graphiql。エディタに次のクエリを入力します-
mutation doSignUp($input:SignUpInput) { signUp(input:$input)
}
サインアップ関数への入力は複合型であるため、graphiqlでクエリ変数を使用する必要があります。このため、最初にクエリに名前を付けてdoSignUpと呼ぶ必要があります。$ inputはクエリ変数です。
次のクエリ変数は、graphiqlのクエリ変数タブに入力する必要があります-
{
"input":{
"email": "abc@abc",
"firstName": "kannan",
"password": "pass@1234"
}
}
エラー配列には、以下に示す検証エラーの詳細が含まれています。
{
"data": {
"signUp": null
},
"errors": [
{
"message": "email not in proper format",
"locations": [
{
"line": 2,
"column": 4
}
],
"path": [
"signUp"
]
}
]
}
以下に示すように、各フィールドに適切な入力を入力する必要があります-
{
"input":{
"email": "[email protected]",
"firstName": "kannan",
"password": "pass@1234"
}
}
応答は次のとおりです-
{
"data": {
"signUp": "success"
}
}
ここで、以下のクエリでは、パスワードを割り当てていません。
{
"input":{
"email": "[email protected]",
"firstName": "kannan"
}
}
必須フィールドが指定されていない場合、qraphqlサーバーは次のエラーを表示します-
{
"errors": [
{
"message": "Variable \"$input\" got invalid value {\"email\":\"[email protected]\",\"firstName\":\"kannan\"}; Field value.password of required type String! was not provided.",
"locations": [
{
"line": 1,
"column": 19
}
]
}
]
}
Webアプリケーションは、データを非同期で(バックグラウンドで)送受信します。AJAXを使用すると、Webサイトはページを更新せずに画面にコンテンツをロードできます。jQueryはAJAX機能のためのいくつかのメソッドを提供するため、AJAXをより簡単に使用できます。この章では、GraphQLをjQueryと統合する方法を学びます。
クライアントサーバーアーキテクチャを使用するアプリケーションについて考えてみます。GraphQLサーバーからのデータを要求するフロントエンドWebページを構築できます。Webページは、jQueryを使用してGraphQLサーバーに対してAJAX呼び出しを行います。
GraphQLをJQueryと統合するために、GraphiQLリクエストヘッダーを調べて、リクエストパラメーターを理解しましょう。
を開始します hello-worldアプリ(関連する図については第6章を参照してください)。GraphiQLウィンドウにgraphqlクエリ{greeting}を入力します。右クリックして検査するか、Chromeで(ctrl + shift + I)を押して、以下に示すようにネットワークタブに移動します-
シンプルから hello-world たとえば、私たちはそれを理解することができます http method 使用されている POST。ブラウザで、ヘッダーセクションまで下にスクロールして、リクエストペイロードを表示します 。
クリックしたら view code、chromeのリクエストペイロードセクションに次のように表示されます。
{"query":"{\n greeting\n}","variables":null,"operationName":null}
リクエストURLにも注意してください。 http://localhost:9000/graphql これは、クライアントアプリケーションから呼び出す必要があります。
図
段階的なプロセスを使用してGraphQLをJQueryと統合する方法を理解しましょう。
サーバーのセットアップ
次の手順を使用してサーバーをセットアップする方法を学習します-
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
名前の付いたフォルダを作成します jquery-server-app。ターミナルからディレクトリをjquery-server-appに変更します。環境設定の章で説明されている手順3〜5に従います。
ステップ2-スキーマを作成する
プロジェクトフォルダーにschema.graphqlファイルを追加します jquery-server-app 次のコードを追加します-
type Query
{
greeting: String
sayHello(name:String!):String
}
ファイルには2つのクエリが定義されています greeting そして sayHello。sayHelloクエリは文字列パラメータを受け入れ、別の文字列を返します。sayHello()関数のパラメーターがnullではありません。
ステップ3-リゾルバを作成する
プロジェクトフォルダにファイルresolvers.jsを作成し、次のコードを追加します-
const Query =
{
greeting: () => 'Hello GraphQL From TutorialsPoint !!' ,
sayHello:(root,args,context,info) => `Hi ${args.name} GraphQL server says Hello to you!!`
}
module.exports = {Query}
ここに、 greeting そして sayHello2つのリゾルバです。sayHelloリゾルバーでは、nameパラメーターに渡された値にargsを介してアクセスできます。モジュール外のリゾルバー関数にアクセスするには、Queryオブジェクトを使用してエクスポートする必要がありますmodule.exports。
ステップ4-アプリケーションを実行する
server.jsファイルを作成します。環境設定の章のステップ8を参照してください。ターミナルでコマンドnpmstartを実行します。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
ブラウザを開き、URLを入力します http://localhost:9000/graphiql。エディタに次のクエリを入力します-
{
greeting,
sayHello(name:"Mohtashim")
}
サーバーからの応答は以下のとおりです。
{
"data": {
"greeting": "Hello GraphQL From TutorialsPoint !!",
"sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
}
}
クライアントの設定
すでにサーバーをセットアップしているので、クライアントのセットアップ方法を学習します。
ステップ1-現在のプロジェクトフォルダーの外に新しいフォルダーjquery-client-appを作成します
まず、という名前のフォルダを作成します jquery-client-app プロジェクトフォルダの外。
ステップ2-jQuery統合用のHTMLページindex.htmlを作成します
jqueryでクライアントアプリケーションを作成し、両方のメソッドを呼び出します。以下はのコードです index.html ファイル。ザ・ index.html ボタンが表示されると、ページはサーバーにリクエストを送信します– Greet そして SayHelloクリックされます。$ .ajax()関数を使用して非同期リクエストを行います。
<!DOCTYPE html>
<html>
<head>
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() { $("#btnSayhello").click(function() {
const name = $("#txtName").val(); console.log(name); $("#SayhelloDiv").html('loading....');
$.ajax({url: "http://localhost:9000/graphql", contentType: "application/json",type:'POST', data: JSON.stringify({ query:`{ sayHello(name:"${name}")}`
}),
success: function(result) {
console.log(JSON.stringify(result))
$("#SayhelloDiv").html("<h1>"+result.data.sayHello +"</h1>"); } }); }); $("#btnGreet").click(function() {
$("#greetingDiv").html('loading....'); //https://kannan-first-graphql-app.herokuapp.com/graphql $.ajax({url: "http://localhost:9000/graphql",
contentType: "application/json",
type:'POST',
data: JSON.stringify({
query:`{greeting}`
}),
success: function(result) {
$("#greetingDiv").html("<h1>"+result.data.greeting+"</h1>");
}
});
});
});
</script>
</head>
<body>
<h1>Jquery Client </h1>
<hr/>
<section>
<button id = "btnGreet">Greet</button>
<br/> <br/>
<div id = "greetingDiv"> </div>
</section>
<br/> <br/> <br/>
<hr/>
<section>
Enter a name:<input id = "txtName" type = "text" value = "kannan"/>
<button id = "btnSayhello">SayHello</button>
<div id = "SayhelloDiv"> </div>
</section>
</body>
</html>
このファイルをブラウザで開き、ボタンをクリックして応答を確認します。出力は以下のようになります-
Reactは、ユーザーインターフェイスを構築するためのJavascriptライブラリです。この章では、GraphQLをReactアプリケーションと統合する方法について説明します。
図
反応プロジェクトを設定する最も簡単な方法は、Reactアプリの作成 ツールを使用すること です。以降のセクションでは、サーバーとクライアントの両方をセットアップする方法を学習します。
サーバーのセットアップ
サーバーをセットアップするには、以下の手順に従います-
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
フォルダを作成する react-server-app。ディレクトリを次のように変更します react-server-app ターミナルから。環境設定の章で説明されている手順3〜5に従います。
ステップ2-スキーマを作成する
追加 schema.graphql プロジェクトフォルダ内のファイル react-server-app 次のコードを追加します-
type Query
{
greeting: String
sayHello(name:String!):String
}
このファイルには、greetingとsayHelloの2つのクエリが定義されています。sayHelloクエリは文字列パラメータを受け入れ、別の文字列を返します。sayHello()関数のパラメーターがnullではありません。
ステップ3-リゾルバを作成する
ファイルを作成する resolvers.js プロジェクトフォルダに次のコードを追加します-
const Query =
{
greeting: () => 'Hello GraphQL From TutorialsPoint !!' ,
sayHello:(root,args,context,info) => `Hi ${args.name} GraphQL server says Hello to you!!`
}
module.exports = {Query}
ここで、greetingとsayHelloは2つのリゾルバーです。sayHelloリゾルバーでは、nameパラメーターに渡された値にargsを介してアクセスできます。モジュール外のリゾルバー関数にアクセスするには、module.exportsを使用してQueryオブジェクトをエクスポートする必要があります。
ステップ4-アプリケーションを実行する
server.jsファイルを作成します。環境設定の章のステップ8を参照してください。ターミナルでコマンドnpmstartを実行します。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
ブラウザを開き、URLを入力します http://localhost:9000/graphiql。エディタに次のクエリを入力します-
{
greeting,
sayHello(name:"Mohtashim")
}
サーバーからの応答を以下に示します-
{
"data": {
"greeting": "Hello GraphQL From TutorialsPoint !!",
"sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
}
}
クライアントの設定
クライアント用の新しいターミナルを開きます。クライアントアプリケーションを実行する前に、サーバーターミナルを実行し続ける必要があります。Reactアプリケーションはポート番号3000で実行され、サーバーアプリケーションはポート番号9000で実行されます。
ステップ1-Reactプロジェクトを作成するhello-world-client
クライアント端末で、次のコマンドを入力します-
npx create-react-app hello-world-client
これにより、一般的なReactアプリケーションに必要なすべてのものがインストールされます。ザ・npx ユーティリティと create-react-appツールは、hello-world-clientという名前のプロジェクトを作成します。インストールが完了したら、VSCodeでプロジェクトを開きます。
ステップ2-hello-world-clientを起動します
ターミナルの現在のフォルダーパスをhello-world-clientに変更します。npm startと入力して、プロジェクトを起動します。これにより、ポート3000で開発サーバーが実行され、ブラウザが自動的に開き、インデックスページが読み込まれます。
これは、以下のスクリーンショットに示されています-
ステップ3-アプリコンポーネントを変更する
srcフォルダー内のApp.jsに、2つの関数を追加します。1つはグリーティングをロードし、もう1つはsayHelloメッセージをロードします。
以下は、挨拶のためにGraphQLクエリを送信するloadGreeting関数です。
async function loadGreeting() {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:'{greeting}'})
})
const rsponseBody = await response.json();
return rsponseBody.data.greeting;
console.log("end of function")
}
以下は loadSayhello sayHelloのGraphQLクエリを送信する関数−
async function loadSayhello(name) {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:`{sayHello(name:"${name}")}`})
})
}
完全な App.js ファイルを以下に示します-
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
async function loadGreeting() {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:'{greeting}'})
})
const rsponseBody = await response.json();
return rsponseBody.data.greeting;
console.log("end of function")
}
async function loadSayhello(name) {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:`{sayHello(name:"${name}")}`})
})
const rsponseBody = await response.json();
return rsponseBody.data.sayHello;
}
class App extends Component {
constructor(props) {
super(props);
this.state = {greetingMessage:'',sayHelloMessage:'',userName:''}
this.updateName = this.updateName.bind(this);
this.showSayHelloMessage = this.showSayHelloMessage.bind(this);
this.showGreeting = this.showGreeting.bind(this);
}
showGreeting() {
loadGreeting().then(g => this.setState({greetingMessage:g+" :-)"}))
}
showSayHelloMessage() {
const name = this.state.userName;
console.log(name)
loadSayhello(name).then(m => this.setState({sayHelloMessage:m}))
}
updateName(event) {
this.setState({userName:event.target.value})
}
render() {
return (
<div className = "App">
<header className = "App-header">
<img src = {logo} className = "App-logo" alt = "logo" />
<h1 className = "App-title">Welcome to React</h1>
</header>
<br/><br/>
<section>
<button id = "btnGreet" onClick = {this.showGreeting}>Greet</button>
<br/> <br/>
<div id = "greetingDiv">
<h1>{this.state.greetingMessage}</h1>
</div>
</section>
<hr/>
<section>
Enter a name:<input id = "txtName" type = "text" onChange = {this.updateName}
value = {this.state.userName}/>
<button id = "btnSayhello" onClick = {this.showSayHelloMessage}>SayHello</button>
<br/>
user name is:{this.state.userName} <br/>
<div id = "SayhelloDiv">
<h1>{this.state.sayHelloMessage}</h1>
</div>
</section>
</div>
);
}
}
export default App;
両方のアプリケーションが実行されたら、挨拶ボタンをクリックします。次に、テキストボックスに名前を入力し、sayHelloボタンをクリックします。出力は以下のようになります-
Apollo Serverを使用して、サーバー側でgraphql仕様を構築しました。本番環境に対応したGraphQLサーバーをすばやく簡単に構築できます。それでは、クライアント側について理解しましょう。
Apollo Clientは、GraphQLを使用してクライアントアプリケーションを構築するための最良の方法です。このクライアントは、開発者がGraphQLを使用してデータをフェッチし、任意のJavaScriptフロントエンドで使用できるUIをすばやく構築できるように設計されています。
Apolloクライアントは次のプラットフォームをサポートしています-
シニア番号 | プラットフォームとフレームワーク |
---|---|
1 | Javascript React、Angular、Vue、Meteor、Ember |
2 | WebComponents ポリマー、点灯-アポロ |
3 | Native Mobile Javaを使用したネイティブAndroid、Swiftを使用したネイティブiOS |
キャッシングは、Apolloクライアントの主要な機能の1つです。apollo-boostは、他の多くの依存関係をもたらす便利なパッケージです。
図
次の手順を使用して、ApolloClientを使用してクライアントアプリケーションを構築する方法を見てみましょう。
サーバーのセットアップ
サーバーをセットアップするには、以下の手順に従う必要があります-
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
apollo-server-appフォルダーを作成します。ディレクトリを次のように変更します apollo-server-app ターミナルから。次に、環境設定の章で説明されている手順3〜5に従います。
ステップ2-スキーマを作成する
追加 schema.graphql プロジェクトフォルダ内のファイル apollo-server-app 次のコードを追加します-
type Query
{
students:[Student]
}
type Student {
id:ID!
firstName:String
lastName:String
college:College
}
type College {
id:ID!
name:String
location:String
rating:Float
}
ステップ3-リゾルバを追加する
ファイルを作成する resolvers.js プロジェクトフォルダに次のコードを追加します-
const db = require('./db')
const Query = {
//resolver function for students returns list
students:() => db.students.list(),
}
const Student = {
college:(root) => {
return db.colleges.get(root.collegeId);
}
}
module.exports = {Query,Student}
ステップ4-アプリケーションを実行する
作成する server.jsファイル。環境設定の章のステップ8を参照してください。 ターミナルでコマンドnpmstartを実行し ます。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
ブラウザを開き、URLを入力します http://localhost:9000/graphiql。エディターに次のクエリを入力します。
{
students{
id
firstName
college{
name
}
}
}
クエリに対する応答は次のとおりです-
{
"data": {
"students": [
{
"id": "S1001",
"firstName": "Mohtashim",
"college": {
"name": "CUSAT"
}
},
{
"id": "S1002",
"firstName": "Kannan",
"college": {
"name": "AMU"
}
},
{
"id": "S1003",
"firstName": "Kiran",
"college": {
"name": "AMU"
}
}
]
}
}
クライアントの設定
クライアント用の新しいターミナルを開きます。クライアントアプリケーションを実行する前に、サーバーターミナルを実行し続ける必要があります。Reactアプリケーションはポート番号3000で実行され、サーバーアプリケーションはポート番号9000で実行されます。
ステップ1-Reactアプリケーションを作成する
クライアント端末で、次のコマンドを入力します-
npx create-react-app hello-world-client
これにより、一般的なReactアプリケーションに必要なすべてのものがインストールされます。npxユーティリティとcreate-react-appツールは、名前の付いたプロジェクトを作成しますhello-world-client。インストールが完了したら、VSCodeでプロジェクトを開きます。
ステップ2-hello-world-clientを起動します
ターミナルの現在のフォルダパスをに変更します hello-world-client。npm startと入力して、プロジェクトを起動します。これにより、ポート3000で開発サーバーが実行され、ブラウザが自動的に開き、インデックスページが読み込まれます。
これは、以下のスクリーンショットに示されています-
ステップ3-Apolloクライアントライブラリをインストールする
Apolloクライアントをインストールするには、新しいターミナルを開き、現在のプロジェクトフォルダーパスに移動します。次のコマンドを入力します-
npm install apollo-boost graphql
これにより、クライアント側のgraphqlライブラリとApolloBoostパッケージがダウンロードされます。apollo-boostの依存関係にnpmviewと入力すると、これをクロスチェックできます。これには、以下に示すように多くの依存関係があります-
{
'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ファイルのアプリコンポーネントを変更する
Apollo Clientを使用すると、フェッチAPIを使用せずにサーバーを直接呼び出すことができます。また、クエリとミューテーションは、バックティック表記で作成された文字列に埋め込まないでください。これは、gql関数はクエリを直接解析します。つまり、プログラマーはGraphiQLツールでクエリを作成するときと同じ方法で直接クエリを作成できます。 gql は、バックティック表記で書かれたテンプレート文字列をgraphqlクエリオブジェクトに解析するタグ関数です。ApolloClientクエリメソッドはpromiseを返します。
次のコードスニペットは、Apolloクライアントをインポートする方法を示しています-
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const endPointUrl = 'http://localhost:9000/graphql'
const client = new ApolloClient({
link: new HttpLink({uri:endPointUrl}),
cache:new InMemoryCache()
});
前の章では、HTTPリクエストにフェッチAPIを使用する方法について説明しました。次のコードは、使用方法を示していますgql関数。ザ・loadStudentsAsync 関数はgraphqlクライアントを使用してサーバーにクエリを実行します。
async function loadStudentsAsync() {
const query = gql`
{
students{
id
firstName
lastName
college{
name
}
}
}`
const {data} = await client.query({query}) ;
return data.students;
}
あなたは維持する必要があるだけです index.js に srcパブリックフォルダー内のフォルダーとindex.html。自動生成された他のすべてのファイルは削除できます。
ディレクトリ構造を以下に示します-
hello-world-client /
-->node_modules
-->public
index.html
-->src
index.js
-->package.json
以下は index.js 反応アプリケーションで-
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
// apollo client
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
import gql from 'graphql-tag'
const endPointUrl = 'http://localhost:9000/graphql'
const client = new ApolloClient({
link: new HttpLink({uri:endPointUrl}),
cache:new InMemoryCache()
});
async function loadStudentsAsync() {
const query = gql`
{
students{
id
firstName
lastName
college{
name
}
}
}
`
const {data} = await client.query({query}) ;
return data.students;
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
students:[]
}
this.studentTemplate = [];
}
async loadStudents() {
const studentData = await loadStudentsAsync();
this.setState({
students: studentData
})
console.log("loadStudents")
}
render() {
return(
<div>
<input type = "button" value = "loadStudents" onClick = {this.loadStudents.bind(this)}/>
<div>
<br/>
<hr/>
<table border = "3">
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>college Name</td>
</tr>
</thead>
<tbody>
{
this.state.students.map(s => {
return (
<tr key = {s.id}>
<td>
{s.firstName}
</td>
<td>
{s.lastName}
</td>
<td>
{s.college.name}
</td>
</tr>
)
})
}
</tbody>
</table>
</div>
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
以下に示すようにloadStudentsボタンをクリックすると、reactアプリケーションはGraphQLサーバーから学生をロードします-
認証は、ユーザーまたはプロセスのIDを検証するプロセスまたはアクションです。アプリケーションがユーザーを認証して、匿名ユーザーがデータを利用できないようにすることが重要です。このセクションでは、GraphQLクライアントを認証する方法を学習します。
Express JWT
この例では、jQueryを使用してクライアントアプリケーションを作成します。リクエストを認証するために、 express-jwt サーバー側のモジュール。
express-jwtモジュールは、JWTトークンを使用してHTTPリクエストを認証できるミドルウェアです。JSON Web Token(JWT)は、ログインしたユーザーを識別する長い文字列です。
ユーザーが正常にログインすると、サーバーはJWTトークンを生成します。このトークンは、ログを明確に識別します。つまり、トークンはユーザーのIDを表したものです。したがって、次回、クライアントがサーバーにアクセスすると、必要なリソースを取得するためにこのトークンを提示する必要があります。クライアントは、モバイルアプリケーションまたはWebアプリケーションのいずれかです。
図
この図を理解するために、段階的な手順に従います。
サーバーのセットアップ
サーバーを設定する手順は次のとおりです-
ステップ1-プロジェクトに必要な依存関係をダウンロードしてインストールする
フォルダを作成する auth-server-app。ディレクトリを次のように変更します auth-server-app ターミナルから。環境設定の章で説明されている手順3〜5に従います。
ステップ2-スキーマを作成する
schema.graphql auth-server-apptype Query
{
greetingWithAuth:String
}
ステップ3-リゾルバを追加する
ファイルを作成する resolvers.js プロジェクトフォルダに次のコードを追加します-
リゾルバーは、認証されたユーザーオブジェクトがGraphQLのコンテキストオブジェクトで使用可能かどうかを確認します。認証されたユーザーが利用できない場合は、例外が発生します。
const db = require('./db')
const Query = {
greetingWithAuth:(root,args,context,info) => {
//check if the context.user is null
if (!context.user) {
throw new Error('Unauthorized');
}
return "Hello from TutorialsPoint, welcome back : "+context.user.firstName;
}
}
module.exports = {Query}
ステップ4-Server.jsファイルを作成する
認証ミドルウェアは、JSONWebトークンを使用して発信者を認証します。認証用のURLは http://localhost:9000/login。
これは後処理です。ユーザーは、バックエンドから検証される電子メールとパスワードを送信する必要があります。jwt.signメソッドを使用して有効なトークンが生成された場合、クライアントは後続のリクエストのためにこれをヘッダーで送信する必要があります。
トークンが有効な場合、req.userは、認証とアクセス制御のために後のミドルウェアで使用されるようにデコードされたJSONオブジェクトで設定されます。
次のコードは、jsonwebtokenとexpress-jwtの2つのモジュールを使用してリクエストを認証します。
ユーザーがをクリックすると greetボタンをクリックすると、/ graphqlルートのリクエストが発行されます。ユーザーが認証されていない場合、ユーザーは自分自身を認証するように求められます。
ユーザーには、電子メールIDとパスワードを受け入れるフォームが表示されます。この例では、/ loginルートがユーザーの認証を担当します。
/ loginルートは、ユーザーが提供した資格情報と一致するものがデータベースで見つかったかどうかを確認します。
資格情報が無効な場合、HTTP401例外がユーザーに返されます。
資格情報が有効な場合、トークンはサーバーによって生成されます。このトークンは、ユーザーへの応答の一部として送信されます。これは、jwt.sign関数によって実行されます。
const expressJwt = require('express-jwt');
const jwt = require('jsonwebtoken');
//private key
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');
app.post('/login', (req, res) => {
const {email, password} = req.body;
//check database
const user = db.students.list().find((user) => user.email === email);
if (!(user && user.password === password)) {
res.sendStatus(401);
return;
}
//generate a token based on private key, token doesn't have an expiry
const token = jwt.sign({sub: user.id}, jwtSecret);
res.send({token});
});
リクエストごとに、app.use()関数が呼び出されます。これにより、expressJWTミドルウェアが呼び出されます。このミドルウェアは、JSONWebトークンをデコードします。トークンに保存されているユーザーIDが取得され、プロパティユーザーとしてリクエストオブジェクトに保存されます。
//decodes the JWT and stores in request object
app.use(expressJwt({
secret: jwtSecret,
credentialsRequired: false
}));
GraphQLコンテキスト内でユーザープロパティを利用できるようにするために、このプロパティは context 以下に示すオブジェクト-
//Make req.user available to GraphQL context
app.use('/graphql', graphqlExpress((req) => ({
schema,
context: {user: req.user &&apm; db.students.get(req.user.sub)}
})));
作成する server.js 現在のフォルダパスにあります。完全なserver.jsファイルは次のとおりです-
const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const expressJwt = require('express-jwt'); //auth
const jwt = require('jsonwebtoken'); //auth
const db = require('./db');
var port = process.env.PORT || 9000
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');
const app = express();
const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})
app.use(cors(), bodyParser.json(), expressJwt({
secret: jwtSecret,
credentialsRequired: false
}));
const {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql', graphqlExpress((req) => ({
schema,
context: {user: req.user && db.students.get(req.user.sub)}
})));
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
//authenticate students
app.post('/login', (req, res) => {
const email = req.body.email;
const password = req.body.password;
const user = db.students.list().find((user) => user.email === email);
if (!(user && user.password === password)) {
res.sendStatus(401);
return;
}
const token = jwt.sign({sub: user.id}, jwtSecret);
res.send({token});
});
app.listen(port, () => console.info(`Server started on port ${port}`));
ステップ5-アプリケーションを実行する
ターミナルでコマンドnpmstartを実行し ます。サーバーは9000ポートで稼働します。ここでは、アプリケーションをテストするためのクライアントとしてGraphiQLを使用します。
ブラウザを開き、URLを入力します http://localhost:9000/graphiql。エディタに次のクエリを入力します-
{
greetingWithAuth
}
以下の応答では、認証されたユーザーではないため、エラーが発生しました。
{
"data": {
"greetingWithAuth": null
},
"errors": [
{
"message": "Unauthorized",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"greetingWithAuth"
]
}
]
}
次のセクションでは、認証するクライアントアプリケーションを作成しましょう。
JQueryクライアントのセットアップ
クライアントアプリケーションでは、スキーマを呼び出す挨拶ボタンが提供されます greetingWithAuth。ログインせずにボタンをクリックすると、以下のようなエラーメッセージが表示されます-
データベースで利用可能なユーザーでログインすると、次の画面が表示されます-
アクセスするために greeting、最初にURLにアクセスする必要があります http://localhost:9000/login 以下のようにルーティングします。
応答には、サーバーから生成されたトークンが含まれます。
$.ajax({
url:"http://localhost:9000/login",
contentType:"application/json",
type:"POST",
data:JSON.stringify({email,password}),
success:function(response) {
loginToken = response.token;
$('#authStatus') .html("authenticated successfully") .css({"color":"green",'font-weight':'bold'}); $("#greetingDiv").html('').css({'color':''});
},
error:(xhr,err) => alert('error')
})
ログインに成功すると、以下のようにgreetingWithAuthスキーマにアクセスできます。ベアラートークンを使用した後続のすべてのリクエストには、Authorizationheaderが必要です。
{
url: "http://localhost:9000/graphql",
contentType: "application/json",
headers: {"Authorization": 'bearer '+loginToken}, type:'POST',
data: JSON.stringify({
query:`{greetingWithAuth}`
}
以下はindex.htmlのコードです-
<!DOCTYPE html>
<html>
<head>
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() { let loginToken = ""; $("#btnGreet").click(function() {
$.ajax({url: "http://localhost:9000/graphql", contentType: "application/json", headers: {"Authorization": 'bearer '+loginToken}, type:'POST', data: JSON.stringify({ query:`{greetingWithAuth}` }), success: function(result) { $("#greetingDiv").html("<h1>"+result.data.greetingWithAuth+"</h1>")
},
error:function(jQxhr,error) {
if(jQxhr.status == 401) {
$("#greetingDiv").html('please authenticate first!!') .css({"color":"red",'font-weight':'bold'}) return; } $("#greetingDiv").html('error').css("color","red");
}
});
});
$('#btnAuthenticate').click(function() { var email = $("#txtEmail").val();
var password = $("#txtPwd").val(); if(email && password) { $.ajax({
url:"http://localhost:9000/login",
contentType:"application/json",
type:"POST",
data:JSON.stringify({email,password}),
success:function(response) {
loginToken = response.token;
$('#authStatus') .html("authenticated successfully") .css({"color":"green",'font-weight':'bold'}); $("#greetingDiv").html('').css({'color':''});
},
error:(xhr,err) => alert('error')
})
}else alert("email and pwd empty")
})
});
</script>
</head>
<body>
<h1> GraphQL Authentication </h1>
<hr/>
<section>
<button id = "btnGreet">Greet</button>
<br/> <br/>
<div id = "greetingDiv"></div>
</section>
<br/> <br/> <br/>
<hr/>
<section id = "LoginSection">
<header>
<h2>*Login first to access greeting </h2>
</header>
<input type = "text" value = "[email protected]" placeholder = "enter email" id = "txtEmail"/>
<br/>
<input type = "password" value = "pass123" placeholder = "enter password" id = "txtPwd"/>
<br/>
<input type = "button" id = "btnAuthenticate" value = "Login"/>
<p id = "authStatus"></p>
</section>
</body>
</html>
キャッシングは、と呼ばれる一時ストレージ領域にデータを保存するプロセスです。 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サーバーからの時間が常に最新になり、データがキャッシュされないことがわかります。