Next.js の Web API 機能
Next.js では、pages/api
ディレクトリ以下に TypeScript (JavaScript) コードを配置するだけで、クライアントサイド JavaScript から呼び出せる API を定義することができます。
例えば、次のようなファイルを作成します。
あとは、Next.js サーバーを起動した状態で、/api/hello
というエンドポイントにアクセスすると、次のような JSON データを取得できます。
API 機能は次のような用途に使用することができます。
- フォームに入力された値が POST されたときにサーバーサイドで DB に保存する
- 3rd パーティ製の Web API の呼び出しを中継する
このような機能を実装するには、データベースのパスワードや、3rd パーティ製 Web API のアクセスキーなどが必要になりますが、そういった情報は Next.js サーバ側の環境変数などに保存しておくことができます。
そうすれば、API の実装コードから process.env.XXX_ACCESS_KEY
のように参照できます。
pages/api
ディレクトリ以下の実装内容が、クライアントに見られてしまうことはありません。
API のコードは Next.js サーバー上で実行されるため、この API 機能を使用するには、Web サイトのホスティング時に Next.js サーバー (next start
) が必要です。
必然的に、Vercel のサービス などを使ってホスティングすることになるため、静的サーバー用の HTML ファイル群を生成する next exports
コマンドは実行できなくなります(pages/api
以下にファイルを作成すると、next build
までしか成功しなくなります)。
クエリパラメーターに対応する
例えば、ゲームの情報を取得する API として /api/games
というエンドポイントを定義するとします。
パラメーターとして 1
などのゲーム ID を指定する場合、次のような 2 通りの指定方法が考えられます。
/api/games/1
(REST 形式の URL にする)/api/games?id=1
(クエリ文字列を付加する)
以下、それぞれの実装方法を説明します。
REST 形式
/api/games/1
という REST API 風の URL でアクセスしたいときは、通常のページコンポーネントと同様のダイナミックルーティングの機能を使って API を実装します。
例えば、/api/games/1
や /api/games/2
のような URL をハンドルするには、pages/api/games/[id].ts
というファイルを作成します。
id
部分に指定されたパラメーターの値は、ハンドラー関数に渡される NextApiRequest
オブジェクトを使って、req.query.id
のように参照することができます。
例えば、/api/games/3
というアドレスでアクセスすると、次のような JSON データが返されます。
クエリ文字列形式
/api/games?id=1
といったクエリ文字列の形で指定されたパラメータ (?id=1
) を取得するには、API を実装するファイルを、pages/api/games.ts
あるいは pages/api/games/index.ts
という名前で作成します。
パラメーターの参照方法は前述の方法と同じで、req.query.id
のように参照できます。
例えば、/api/games?id=2
というアドレスでアクセスすると、次のような JSON データが返されます。
どちらの形式を使うべきか?
どちらでもよいですが、パラメーターが 1 つの場合は REST 形式 (pages/api/games/[id].ts
) で定義するとシンプルです。
API を呼び出すときに、いちいち id
のようなパラメーター名を指定する必要がありません(呼び出し例: /api/games/1
)。
逆にパラメーターを複数指定する可能性があって、その指定順序に制約がない場合は、クエリ文字列を使った形式 (pages/api/games.tsx
) で定義するのがよいと思います。
呼び出し時にキー&バリューの形でパラメーターを指定するので、間違った値を指定してしまうミスが減ります(呼び出し例: /api/games?genre=ACT&year=1990
)。
React コンポーネントから API を呼び出す
上記のように定義した API を React コンポーネントの実装から呼び出すには、useSWR
フックを使用するのが簡単です。
このフックは Vercel が swr
パッケージとして提供しています。
先に、Game
インタフェースを共有できるように、ライブラリファイルとして抽出しておきます。
次のコンポーネントでは、クライアントサイド JavaScript で /api/games/1
というエンドポイントの API を呼び出しています。
useSWR
フックの型パラメーターとして Game
を指定することで、戻り値の data
変数の型が Game | undefined
になります(データ取得が完了するまで undefined
になる)。
関連記事
- Next.js のダイナミックルーティング機能を利用する (getStaticPaths, getStaticProps, getServerSideProps)
- Next.js でコンポーネント内に直接 CSS を記述する (styled-jsx)
- Next.js で全ページ共通のレイアウトを定義する(Layout コンポーネント)
- Next.js で各ページの head 要素をカスタマイズする (next/head)
- Next.js のプリレンダリング機能を使用する (getStaticProps)
- Next.js のプロジェクトを TypeScript 化する
- Next.js アプリのソースコードを GitHub で管理する