Next.js (App Router) で、同一ドメインのAPIにfetchする際の覚書
Next.jsのApp Routerでのアプリ構築中に、Page Routerとfetchの挙動・仕様の違いに遭遇しました。以前のNext.jsとは異なり、相対パスでのAPIリクエストがエラーになります。next/headersを使用して現在のサイトのドメインを取得し、fetchのURLに渡すことで解決できます。App Routerでは、next/headersのheaders()からプロトコルやホストを取得できるため、app/api/route.tsなどで作成したAPIをapp/page.tsなどからfetchすることができます。参考になる記事やGithubの情報もあります。
広告ここから
広告ここまで
目次
Next.jsのApp Routerでアプリを構築中、Page Routerとfetch
の挙動・仕様が異なる様子でしたので、ざっとまとめました。
これまでのNext.jsとの違い
fetch('/api/xxx')
のように、相対パスでAPIリクエストを投げることがありました。
これがApp Routerではエラーになります。
Unhandled Runtime Error
Error: Failed to parse URL from /api/prices
サーバーサイドでfetch
しようとしてエラーになっている・・・と思われます。
next/headers
で今いるサイトのドメインを取得する
相対パスが使えないので、今動かしているNext.jsアプリのドメインを、fetch
のurlに渡すようにしてみました。
import { Metadata } from 'next'
import { headers } from 'next/headers'
export const metadata: Metadata = {
title: 'Products',
}
export default async function Page() {
const headersData = headers()
const host = headersData.get('host')
const protocol = headersData.get('x-forwarded-proto') ?? host.startWith('localhost') ? 'http' : 'https'
const apiBase = `${protocol}://${host}`
const res = await fetch(`${apiBase}/api/prices`, {
next: {
revalidate: 10 * 60 // 10 minutes
}
}).then(data => data.json())
...
localhostではhttpになるので、プロトコルもヘッダー情報から取得します。
Next.js App Routerでは、next/headers
のheaders()
からプロトコルやホストが取得できました。
この方法で、app/api/route.ts
などに作成したAPIを、app/page.ts
などからfetch
できる様子です。