Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8835

NestJSで始めるGraphQLサーバ開発(コードファースト編)

$
0
0

image.png
NestJSは、TypeScriptで記述するバックエンドアプリケーションフレームワークです。デフォルトで DI(Dependency Injection) の仕組みをサポートしており、テスト可能な構成を簡単に作ることができる特徴があります。
今回の記事ではNestJSを使用して最もシンプルなGraphQLサーバを構築します。
↓完成イメージ
nestjs-graphql.gif

GraphQLの基本

GraphQLは、RESTエンドポイントのように煩雑に管理されたエンドポイントではなく、1つのエンドポイントに対して厳密に型指定されたスキーマとしてAPIを実行します。

image.png

GraphQLについて深くは解説しませんが、以下のリンクがとても参考になります。初学者は一読しておくことをオススメします。

NestJSでGraphQL

NestJSを使用したGraphQLの開発には2つの方法があります。

  • スキーマファースト
  • コードファースト

スキーマファーストのアプローチでは GraphQL SDL(スキーマ定義言語)をもとにしてTypeScript定義を自動的に生成します。
一方でコードファーストのアプローチでは、デコレータとTypeScriptのクラスのみを使用して対応する GraphQL スキーマを生成します。

今回はコードファーストのアプローチでGraphQLサーバを作成していきます。
まず始めに nestjsのコマンドラインツール@nestjs/cliをインストールしましょう。インストールができたら nest コマンドが使用できます。早速 NestJSアプリケーションを作成します。

$ npm i -g @nestjs/cli
$ nest new nest-graphql

作成されたNestJSアプリケーションを起動しましょう。

$ cd nest-graphql/
$ npm run start

> nest-graphql@0.0.1 start /Users/daisuke/work/nest-graphql
> ts-node -r tsconfig-paths/register src/main.ts

[Nest] 5868   - 2019-12-03 21:36:33   [NestFactory] Starting Nest application...
[Nest] 5868   - 2019-12-03 21:36:33   [InstanceLoader] AppModule dependencies initialized +28ms
[Nest] 5868   - 2019-12-03 21:36:33   [RoutesResolver] AppController {/}: +10ms
[Nest] 5868   - 2019-12-03 21:36:33   [RouterExplorer] Mapped {/, GET} route +16ms
[Nest] 5868   - 2019-12-03 21:36:33   [NestApplication] Nest application successfully started +6ms

ブラウザで localhost:3000 にアクセスして Hello Wold! が表示されれば準備OKです。
この状態ではまだRESTAPIの形式になっていますね。
image.png

GraphQL 関連ライブラリのインストール

GraphQLサーバを実装していきますので、まずは必要なライブラリをインストールします。

$ npm i --save @nestjs/graphql \
               apollo-server-express \
               graphql-tools \
               graphql \
               type-graphql

REST API用に作られていた app.module.ts を書き換えましょう。
Controller, Service の箇所を GraphQLModule として書き換えました。
.forRoot()メソッドで playground: trueを宣言することで ブラウザ(http://localhost:3000/graphql)で GraphQL IDEを表示できます。autoSchemaFileは自動的に生成されたスキーマが作成されるパスを示しています

app.module.ts
import{Module}from'@nestjs/common';import{GraphQLModule}from'@nestjs/graphql';@Module({imports:[GraphQLModule.forRoot({playground:true,autoSchemaFile:'schema.graphql'}),],})exportclassAppModule{}

playground はアプリケーションがバックグラウンドで実行されている間に、Webブラウザーを開いて http://localhost:3000/graphqlにアクセスすると表示できます。npm run startを実行してアプリケーションを起動してからブラウザを開いてみましょう。

$ npm run start

> nest-graphql@0.0.1 start /Users/daisuke/work/nest-graphql
> ts-node -r tsconfig-paths/register src/main.ts

[Nest] 8832   - 2019-12-03 23:44:15   [NestFactory] Starting Nest application...
[Nest] 8832   - 2019-12-03 23:44:15   [InstanceLoader] AppModule dependencies initialized +26ms
[Nest] 8832   - 2019-12-03 23:44:15   [InstanceLoader] RecipesModule dependencies initialized +1ms
[Nest] 8832   - 2019-12-03 23:44:15   [InstanceLoader] GraphQLModule dependencies initialized +0ms
[Nest] 8832   - 2019-12-03 23:44:15   [NestApplication] Nest application successfully started +82ms

image.png

Moduleを作成

NestJSの流儀に従って、まずはModuleを作成します。例としてレシピの一覧が表示できるアプリケーションを想定しています。

$ nest generate module recipes
CREATE /src/recipes/recipes.module.ts (84 bytes)
UPDATE /src/app.module.ts (325 bytes)

app.module.ts に自動的に RecipesModule が追加されるので確認しておきましょう。

import{Module}from'@nestjs/common';import{GraphQLModule}from'@nestjs/graphql';import{RecipesModule}from'./recipes/recipes.module';@Module({imports:[GraphQLModule.forRoot({playground:true,autoSchemaFile:'schema.graphql',}),RecipesModule,// <-- 自動的に追加される],})exportclassAppModule{}

Modelを作成

次に Model を作成します。
type-graphql のライブラリから各種デコレータで宣言するものを import します。

$ nest generate class recipes/recipe
CREATE /src/recipes/recipe.spec.ts (147 bytes)
CREATE /src/recipes/recipe.ts (23 bytes)
import{Field,ID,ObjectType}from'type-graphql';@ObjectType()exportclassRecipe{@Field(type=>ID)id:string;@Field()title:string;}

Resolverを作成

最後にクエリの操作を行うリゾルバを作成します。

$ nest generate resolver recipes
CREATE /src/recipes/recipes.resolver.spec.ts (477 bytes)
CREATE /src/recipes/recipes.resolver.ts (98 bytes)
UPDATE /src/recipes/recipes.module.ts (170 bytes)

このResolverに Query、Mutation、Subscriptionを実装していきます。
今回は簡単のため、データベースには接続せずにレシピの一覧を返却する処理(Query)を実装しています。

import{Resolver,Query,Args}from'@nestjs/graphql';import{Recipe}from'./recipe';constrecipeTable=[{id:'1',title:'鯖の味噌煮',},{id:'2',title:'ミートソーススパゲティ',},{id:'3',title:'豚の生姜焼',},];@Resolver('Recipes')exportclassRecipesResolver{@Query(returns=>[Recipe])asyncrecipes():Promise<Recipe[]>{returnrecipeTable;}}

ここまででディレクトリ構成は以下のようになっています。

src$ tree -L 2
.
├── app.module.ts
├── main.ts
└── recipes
    ├── recipe.spec.ts
    ├── recipe.ts
    ├── recipes.module.ts
    ├── recipes.resolver.spec.ts
    └── recipes.resolver.ts

スキーマの作成

あとはアプリケーションを起動するとスキーマが自動的に作成されます。

$ npm run start

scema.graphql にスキーマが自動的に作成されています。

#-----------------------------------------------#!!!THISFILEWASGENERATEDBYTYPE-GRAPHQL!!!#!!!DONOTMODIFYTHISFILEBYYOURSELF!!!#-----------------------------------------------typeQuery{recipes:[Recipe!]!}typeRecipe{id:ID!title:String!}

動作確認をしましょう。
http://localhost:3000/graphqlにアクセスしてクエリを実行します。
確かにフィールドごとに選択されて Query が実行できていますね。
nestjs-graphql.gif

NestJSを使用することで、モデルに対してデコレータを付与するだけでシンプルかつ簡単に実装できました。

NestJSは適切にDIをすることでコードのテスタビリティをあげることができる強力なフレームワークです。
GraphQLサーバを組む場合にも威力を発揮できる可能性があり魅力的ですね。


Viewing all articles
Browse latest Browse all 8835

Trending Articles