環境構築
前のページでも述べた通り、GraphQLはAPIのための強力なクエリ言語であり、既存のデータでクエリを実行するための実行環境でもあります。これは、REST APIで一般的に見られる多くの問題を解決するエレガントなアプローチです。背景については、GraphQLとRESTの比較を読んで下さい。
GraphQLとTypeScriptを組み合わせることで、GraphQLクエリの型安全性を向上 させてエンドツーエンドの型付けを行うことができます。
本セクションでは、GraphQLの基本的な理解を前提として組み込みの
@nestjs/graphql
モジュールの操作方法にフォーカスします。GraphQLモジュールは、Apolloサーバ(@nestjs/apollo
ドライバ)およびMercurius(@nestjs/mercurius
を使う)を使うように設定できます 。これらの実績あるGraphQLのパッケージの公式インテグレーションを提供することで、NestJSでGraphQLを簡単に利用できます。
まずは、以下のコマンドを入力してください。
# For Express and Apollo (default)
npm i @nestjs/graphql @nestjs/apollo graphql apollo-server-express
# For Fastify and Apollo
# npm i @nestjs/graphql @nestjs/apollo graphql apollo-server-fastify
# For Fastify and Mercurius
# npm i @nestjs/graphql @nestjs/mercurius graphql [email protected]^9
注意
@nestjs/[email protected]>=9
と@nestjs/apollo^10
のパッケージはApollo v3に対応していますが (詳細はApollo Server 3 migration guideを参照してください)、 @nestjs/[email protected]^8
はApollo v2([email protected]
パッケージなど) のみ対応しています。NestJSでは、GraphQLアプリを開発する方法として、コードファースト方式とスキーマファースト方式の2つを提供しています。これはあなたにとって最適な方を選んでください。このGraphQLのセクションでは、コードファーストとスキーマファーストの2つに大きく分かれています。
コードファーストのアプローチでは、デコレータとTypeScriptクラスを使って対応するGraphQLスキーマを生成します。このアプローチはTypeScriptのみで作業を行い、言語構文間のコンテキスト切り替えを避けたい場合に有効です。
スキーマファーストのアプローチでは、GraphQL SDLファイルを扱います。SDL(Schema Definition Language)は言語に関係なく、異なるプラットフォーム間でスキーマを共有するための方法です。NestJSはGraphQLスキーマに基づいてTypeScriptの定義を自動的に生成し、冗長な定形コードを書く手間を省略します。
メモ
以下の章では、
@nestjs/apollo
パッケージを統合していきます。パッケージのインストールが完了すれば、
GraphQLModule
をインポートし、forRoot()
スタティックメソッドで設定できます。import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
}),
],
})
export class AppModule {}
forRoot()
メソッドは引数としてオプション・オブジェクトを受け取ります。これらのオプションは、基盤となるドライバのインスタンスに渡されます。例えば、PlayGroundを無効にしてデバッグモードをオフにしたい時は以下のようにします。
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
debug: false,
playground: false,
}),
],
})
export class AppModule {}
この場合、これらのオプションは
ApolloServer
コンストラクタに転送されます。PlayGroundは、ブラウザのGraphQL IDEで、デフォルトではGraphQLサーバと同じURLで利用できます。PlayGroundにアクセスするには、基本的なGraphQLサーバが設定されて、実行されている必要があります。今すぐ動作を確認するためには、本ページで動作するサンプルをインストールして構築できます。
または、これらの コードのサンプルに従っている場合はResolverのセクションの手順を完了するとPlayGroundにアクセスできるようになります。
この状態で、アプリケーションがバックグラウンドで動いている状態でWebブラウザを開き、
http:localhost:3000/graphql
に移動できます。すると、以下のようにGraphQL PlayGroundが表示されます。
引用:NestJS公式docs
また、
@nestjs/graphql
モジュールの便利な機能として、複数のエンドポイントを同時に提供できます。これにより、どのモジュールをどのエンドポイントに含めるかを決めることができます。デフォルトでは、GraphQLはアプリ全体を通してResolverを検索します。このスキャンをモジュールのサブセットのみに制限するには
include
プロパティを使用します。GraphQLModule.forRoot({
include: [CatsModule],
}),
注意
一つのアプリケーションで複数のGraphQLエンドポイントで
apollo-server-fastify
パッケージを使用する場合は、GraphQLModule
の設定でdisableHealthCheck
設定を有効にすることを確認してください。コードファーストのアプローチでは、デコレータとTypeScriptのクラスを使って対応するGraphQLのスキーマを生成します。
コードファーストのアプローチを使用するには、まず
options
オブジェクトにautoSchemaFile
プロパティを追加することがあります。GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),
autoSchemaFile
プロパティの値は、自動的に生成されるスキーマが作成されるパスです。また、スキーマは直接書き込む形でメモリ内に生成できます。これを有効にするには、autoSchemaFile
プロパティをtrue
に設定します。GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
}),
デフォルトでは、生成されたスキーマの型は含まれるモジュールで定義されている順番に並べます。スキーマを辞書順に並べるためには、
sortSchema
プロパティをtrue
に設定します。GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
sortSchema: true,
}),
公式のサンプルは以下のリンクからアクセスできます。
スキーマファーストのアプローチを取るには、まずoptionsオブジェクトにtypePathsプロパティを追加します。typePathsプロパティは、GraphQLModuleがあなたの書いたGraphQL SDLスキーマ定義ファイルをどこで探すのかを示します。これらのファイルはメモリ上で結合されま す。
これによって、スキーマをいくつかのファイルに分割し、Resolverの近くに配置できます。
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
typePaths: ['./**/*.graphql'],
}),
また、通常、GraphQL SDLの型に対応するTypeScriptの定義(
class
あるいはinterface
)が必要になります。対応するTypeScriptの定義を手作業で行うのは大変なので、@nestjs/graphql
パッケージからTypeScriptの定義を自動生成しましょう。この機能を有効にするには、GraphQLModule
を設定する際にdefinitions
オプションプロパティを追加します。GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
typePaths: ['./**/*.graphql'],
definitions: {
path: join(process.cwd(), 'src/graphql.ts'),
},
}),
definitions
オブジェクトのpath
プロパティは、生成されたTypeScriptの出力を保存する場所を示しています。デフォルトでは、生成されるすべてのTypeScriptの型はinterface
として作成されます。代わりにクラスを生成するには、outputAs
プロパティに'class'
という値を設定してください。GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
typePaths: ['./**/*.graphql'],
definitions: {
path: join(process.cwd(), 'src/graphql.ts'),
outputAs: 'class',
},
}),
上記の方法では、アプリケーションが起動するたびに動的にTypeScriptの定義が生成されます。あるいは、オンデマンドでこれらを生成するシンプルなスクリプトを構築するのが望ましいかもしれません。
例えば、以下のようなスクリプトを
generate-typings.ts
で作成します。import { GraphQLDefinitionsFactory } from '@nestjs/graphql';
import { join } from 'path';
const definitionsFactory = new GraphQLDefinitionsFactory();
definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.ts'),
outputAs: 'class',
});
そして、以下のコマンドを入力してください。
ts-node generate-typing
メモ
予めスクリプトをコンパイルしておき(例:
tsc
コマンドで実行)、node
で実行することもできます。(とは言っても、ts-node
を使えばTypeScriptをスクリプトファイルとして実行できるので前者の方を推奨します)スクリプトのウォッチモード(拡張子
.gql
ファイルが変更されると自動的にコードを生成するモード)を有効にするには、generate()
メソッドにwatch
オプションを追加してください。definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.ts'),
outputAs: 'class',
watch: true,
emitTypenameField: true,
skipResovlerArgs: true,
});
オブジェクトの種類ごとに追加の
__typename
フィールドを自動生成するなら、emitTypenameField
オプションを有効にします。あと、Resolverを引数のないプレーンフィールドとして生成するには、skipResolverArgs
オプションを有効にします。Last modified 10mo ago