Next.js 13 サーバーコンポーネントでURLパス名を取得する方法
問題点
Next.js 13のApp Router(appディレクトリ)を使用するサーバーコンポーネントで、window.location
を使ってパス名(pathname)を取得しようとしても機能しません。サーバーコンポーネントはブラウザ環境ではないため、window
オブジェクトやlocation
オブジェクトにアクセスできないためです。
サーバーコンポーネントの制約
サーバーコンポーネントはサーバー上でレンダリングされるため、ブラウザ関連のAPIや状態(URLパラメーター、HTTPヘッダー、クエリ文字列等)に直接アクセスできません。
推奨解決策: ミドルウェアを利用したカスタムヘッダー
最も信頼性が高く、Vercルチームにも推奨される方法は、ミドルウェアを活用してURL情報をカスタムヘッダーに保存する方法です。
ステップ 1: ミドルウェアの設定
プロジェクトルート(またはsrc
ディレクトリ内)にmiddleware.ts
ファイルを作成します:
import { NextResponse } from 'next/server';
export function middleware(request: Request) {
const url = new URL(request.url);
const requestHeaders = new Headers(request.headers);
// URL情報をカスタムヘッダーに保存
requestHeaders.set('x-url', request.url);
requestHeaders.set('x-origin', url.origin);
requestHeaders.set('x-pathname', url.pathname);
return NextResponse.next({
request: {
headers: requestHeaders
}
});
}
ステップ 2: サーバーコンポーネントでの情報取得
サーバーコンポーネント内でheaders
関数を使用し、カスタムヘッダーから情報を取得します:
import { headers } from 'next/headers';
export default function Page() {
const headersList = headers();
const headerUrl = headersList.get('x-url') ?? '';
const pathname = headersList.get('x-pathname') ?? '';
const origin = headersList.get('x-origin') ?? '';
console.log('現在のパス名:', pathname);
// コンポーネントのレンダリング処理...
}
パフォーマンスと制限に関する注意点
重要な考慮事項
headers()
関数の使用は動的レンダリングを引き起こします。つまり、Next.jsはリクエスト時に毎回サーバーサイドでコンポーネントをレンダリングします。
// headers()を使う → 動的レンダリング
const headersList = headers();
// cookies()を使う → 動的レンダリング
const cookiesList = cookies();
静的なページのパフォーマンスを最適化する必要がある場合は、このアプローチを慎重に検討してください。
代替アプローチ: 組み込みヘッダーを利用する (非推奨)
一部のQ&Aで以下の方法が提案されていましたが、推奨されません:
const pathname = headers().get('next-url'); // 非推奨!
なぜ推奨されないか
next-url
ヘッダーはNext.jsの内部使用用であり、突然変更される可能性があります- Vercelのプロダクト責任者が公式に使用を控えるよう推奨
- 予測不可能な動作や将来のバージョンで動作しなくなるリスク
クライアントコンポーネントで使用する場合
サーバーコンポーネントでなくクライアントサイドでパス名を取得する必要がある場合:
'use client';
import { usePathname } from 'next/navigation';
export default function ClientComponent() {
const pathname = usePathname();
return <div>現在のパス: {pathname}</div>;
}
ベストプラクティスのまとめ
ユースケース | 推奨アプローチ |
---|---|
サーバーコンポーネント | カスタムヘッダーを設定したミドルウェア |
クライアントコンポーネント | usePathname フックの使用 |
静的ページの最適化 | URL情報が必須か再検討 |
ミドルウェアを使用するアプローチは、Next.jsの開発チーム推奨の方法ではありませんが、2024年現在、サーバーコンポーネントでURL情報を確実に取得する唯一の安定した手法です。将来的に公式APIが提供される可能性がありますが、現在の実装で実現可能です。