Skip to content

Next.jsでのfetch相対パスエラーの解決

問題の説明

Next.jsのサーバーコンポーネント内でAPIルートを相対パス(/api/users)で呼び出すと、次のエラーが発生します:

js
TypeError: Failed to parse URL from api/users

このエラーは以下のようなコードを実行した際に発生します:

js
const getUsers = async () => {
  const result = await fetch('/api/users', {method: 'GET'});
  if (result.ok) {
    return result.json();
  }
  return [];
}

export default async function IndexPage() {
  const users = await getUsers();
  return <h1>Users: {users.length}</h1>;
}

このエラーが発生するコンテキスト

  • ブラウザ環境では動作する相対パス指定が、サーバーサイド(Node.js環境)では失敗
  • Next.js App Routerを使用したサーバーコンポーネントでのみ発生
  • 開発環境(localhost)でも本番環境でも同様の問題が発生

エラーの根本原因

サーバー環境でのfetchの挙動の違い

ブラウザ環境では、fetch('/api/users')は自動的に現在のドメインに対して相対的なURLを解決しますが、Node.js環境ではこの挙動はサポートされていません。

サーバーサイドで動作するNext.jsのサーバーコンポーネントでは、Node.jsのfetch実装が使用されるため、絶対URLを指定する必要があります。

効果的な解決方法

解決策1: 環境変数による絶対URLの指定

最も確実な方法は、環境変数を使用してベースURLを動的に設定することです。

js
const getUsers = async () => {
  // 環境変数からベースURLを取得
  const baseUrl = process.env.URL;
  const result = await fetch(`${baseUrl}/api/users`, {
    method: 'GET'
  });
  
  if (result.ok) {
    return result.json();
  }
  return [];
}

環境変数の設定方法(.envファイル)

ini
# ローカル開発環境
URL="http://localhost:3000"

# 本番環境(デプロイ先に合わせて変更)
URL="https://your-production-domain.com"

Vercelデプロイ時の注意点

Vercelでは環境ごとに異なるURLが生成されるため、適切な環境変数を設定してください:

ini
# Vercelプレビュー環境
URL=https://${VERCEL_URL}

# Vercel本番環境
URL=https://your-custom-domain.com

Vercelが自動的に提供するVERCEL_URL環境変数を活用しましょう: https://vercel.com/docs/projects/environment-variables/system-environment-variables

解決策2: サーバーコンポーネントからの直接データ取得(推奨)

Next.jsの公式ベストプラクティスでは、APIルート経由でなく直接データソースにアクセスする方法が推奨されています:

js
// 直接データベースや外部APIに接続
import db from '@/lib/db';

export default async function IndexPage() {
  // API経由せず直接データ取得
  const users = await db.users.findMany();
  
  return <h1>Users: {users.length}</h1>;
}

直接取得が推奨される理由

  1. 不要なネットワークオーバーヘッドの削減
  2. ビルド時/実行時のパフォーマンス向上
  3. コードの簡素化とメンテナンス性向上

補足:ビルド時の注意点

サーバーコンポーネントから内部APIを呼び出すとビルド時に失敗するケースがあります。公式ドキュメントでは、このアプローチ自体が非推奨とされています:

⚠️ ビルド時のエラーが発生する理由
Next.jsのビルドプロセス中はアプリケーションが実行されていないため、内部APIルートへのアクセスは失敗します

非推奨パターン例

js
// ※ビルド時に失敗する可能性あり
export default async function BuildPage() {
  const data = await fetch(`${process.env.URL}/api/data`);
  // ...
}

まとめ

Next.jsサーバーコンポーネントでの相対パスfetchエラーを解決するには:

  1. 環境変数を使用した絶対URL指定 → クロス環境対応が可能
  2. API経由せず直接データ取得 → Next.jsの推奨パターン

特に、API経由でのデータ取得には余分なレイテンシが発生するため、サーバーコンポーネントから直接データソースにアクセスするアプローチが最適です。