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/headersheaders()からプロトコルやホストが取得できました。

    この方法で、app/api/route.tsなどに作成したAPIを、app/page.tsなどからfetchできる様子です。

    参考

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark