KJ DEV
How to

Next.jsでGraphQLサーバーを実装する方法

Next.jsはバージョン9でDynamic Routesが追加されてとても便利になりました。

ページのファイルを動的に読み込んでくれるだけではなく、Dynamic RoutesのおかげでAPIの追加も気軽になりました。

これにより決められたディレクトリにパスとなる任意のファイル名でコードを配置すると自動的にルーティングの設定ができます。

Next.jsを使ってGraphQLサーバーを実装する機会があったので、コードと合わせて作り方を紹介したいと思います。

目次
  1. Next.jsでのAPI実装方法
  2. GraphQL用のファイルを追加
  3. GraphQLのメソッドをPOSTに限定する
  4. まとめ

Next.jsでのAPI実装方法

Next.jsでAPIを定義するには```pages/api```ディレクトリにファイルを追加します。

例えば/api/usersというルーティングを設定したい場合は/pages/api/users.jsというファイル名で下記のようなコードです。

1
2
3
4
5
export default async (req, res) => {
  const data = 'User API'
  
  res.json(data) // dataはレスポンスしたいデータ
}

これで/api/usersにアクセスすると「User API」というデータが返ってくるようになります。

GraphQL用のファイルを追加

pages/apiディレクトリでAPIの実装ができることを利用して、GraphQLもapiディレクトリに実装します。

まずはpages/api/graphql.jsを下記のコードで作ります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { graphql, GraphQLSchema, GraphQLObjectType, GraphQLID, GraphQLString, GraphQLInt } from 'graphql'

const UsersType = new GraphQLObjectType({
  name: 'UsersType',
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
  })
})

const UsersQuery = {
  type: UsersType,
  args: {},
  resolve: async (parent, args, context, info) => {
  	const data = [
      { id: 1, name: 'User1'},
      { id: 2, name: 'User2'},
    ]
    return data
  }
}

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'RootQuery',
    fields: () => ({
      users: UsersQuery
    })
  })
})

export default async (req, res) => {
  const query = req.body.query
  const variables = req.body.variables
  const response = await graphql(schema, query, null, null, variables) //

  res.setHeader(`Content-Type`, `application/json; charset=utf-8`)

  return res.end(JSON.stringify(response))
}

これで/api/graphqlにGraphQLのクエリを送るとレスポンスを得られるようになります。

TypeとQueryの定義も一つのファイルに書いていますが、実際に使う時はtypesやqueriesなどに適切にファイルを分割することになります。

GraphQLのメソッドをPOSTに限定する

Next.jsでAPIを定義すると紹介した方法では、リクエストがGETでもPOSTでも同じ処理が走ってしまいます。

そこでメソッドを判定してPOSTのみで処理が走るようにします。

1
2
3
4
5
6
7
8
9
10
11
export default async (req, res) => {
  if (req.method === 'POST') {
  	const query = req.body.query
    const variables = req.body.variables
    const response = await graphql(schema, query, null, null, variables) //

    res.setHeader(`Content-Type`, `application/json; charset=utf-8`)

    return res.json(response)
  }
}

reqオブジェクトでリクエスト時のmethodが取得できます。

これはNext.jsの公式でも紹介されていて今ところ、メソッドをわけるにはreq.methodの値を見て分岐させるしかないようです。

<ExternalLink url="https://nextjs.org/docs/api-routes/introduction" title="Introduction - Documentation | Next.js" />

GrapQLのように1つのメソッドだけ定義したり、コード量が少なければ直接書いても良いと思います。

ですがREST APIのようにGET、POST、PUT、DELETEなどURLが同一でいくつかのアクションに分かれる時は適宜ファイルを分割するのがいいと思います。

まとめ

Dynamic RoutesがサポートされるようになってNext.jsはグンと使いやすくなりました。

ページの実装と合わせてAPIも平行して手軽に開発できるのは大きなメリットです。

React.jsのフレームワークは他にもいくつかありますが、Next.jsは積極的に使っていきたいと思います。

開発で参考になった本

実際に読んでみて開発に役立った本を紹介しています。

これから本格的にデザインシステムを学んで作りたい時にとても参考になる一冊でした。デザインシステムついて幅広く触れられているけど、「tailwindを触ってデザインシステムに興味を持った」という人でも少しずつ取り入れやすいです。