【ITニュース解説】Next.jsで `/` から別ページにリダイレクトしたいときにハマった話
2025年09月14日に「Qiita」が公開したITニュース「Next.jsで `/` から別ページにリダイレクトしたいときにハマった話」について初心者にもわかりやすく解説しています。
ITニュース概要
Next.js開発で、トップページ(/)にアクセスしたユーザーを自動的に別のページへ転送(リダイレクト)する設定方法を解説。開発者が遭遇しやすい問題点とその効果的な解決策を紹介する。
ITニュース解説
Webサイトを開発していると、特定のURLにアクセスしたユーザーを別のURLへ自動的に転送したい、という場面によく遭遇する。この転送処理を「リダイレクト」と呼ぶ。例えば、古くなったページから新しいページへ誘導したり、一時的にメンテナンス中のページへ飛ばしたりする際に利用される。今回、Next.jsというフレームワークを使ってWebアプリケーションを開発する中で、「トップページ(URLが/)にアクセスされたら、自動的に別のページへ転送したい」という要件に直面した。一見すると単純な要件に思えるが、Next.jsならではの特性により、いくつかのハマりどころがあったため、その解決策について詳しく解説する。
まず、リダイレクトという機能について簡単に説明する。ユーザーがブラウザでURLを入力したり、リンクをクリックしたりして特定のページにアクセスしようとした際、WebサーバーまたはクライアントサイドのJavaScriptの指示により、別のURLのページが代わりに表示されるのがリダイレクトだ。これにより、ユーザーは意図しない形で新しいページへと誘導される。
このトップページからのリダイレクト要件を満たすために、いくつかの方法を試したが、それぞれに課題があった。
一つ目に試したのは、Next.jsのプロジェクト全体の設定を記述するnext.config.jsファイル内でredirectsプロパティを設定する方法である。この設定は、Next.jsが起動する際にサーバーサイドで読み込まれ、特定のパスへのリクエストがあった場合に別のパスへ転送するよう指示できる。例えば、/というパスへのリクエストを/homeというパスへリダイレクトするように設定する。しかし、この方法は、ブラウザで直接/と入力してアクセスしたり、ページをリロードしたりした場合には正しく機能するものの、Next.jsのLinkコンポーネントを使ってWebサイト内のナビゲーションで/へ遷移しようとした場合には、なぜかリダイレクトが適用されず、トップページに留まってしまうという問題が発生した。これは、next.config.jsのredirectsが、主にブラウザからの直接リクエストや初回アクセス、ページのリロードといったサーバーへのフルリクエスト時に適用される仕組みであり、Linkコンポーネントのようなクライアントサイドのナビゲーションでは別の挙動をするためである。そのため、サイト内リンクからの遷移を考慮すると、この方法は完全な解決策とはならなかった。
二つ目に検討したのは、ページコンポーネントごとにサーバーサイドでのデータ取得や処理を行うためのgetServerSidePropsという機能を利用する方法だ。この機能は、ページコンポーネントが表示される前にサーバー側で処理を実行できるため、ここでリダイレクトの判定を行い、別のページへ転送する、というアプローチである。具体的には、トップページであるpages/index.tsx(あるいはApp Routerのapp/page.tsxに相当する部分)内でgetServerSidePropsを定義し、もしそのページへのアクセスがあった場合は、リダイレクト先のURLを指定して転送する指示を返す。この方法は確かにリダイレクトを実現できた。しかし、Next.jsには「静的サイト生成(SSG)」という強力な機能があり、事前にHTMLファイルを生成しておくことで、高速なページ表示を実現できる。getServerSidePropsを使うと、そのページは必ずリクエストごとにサーバーサイドで処理される「サーバーサイドレンダリング(SSR)」となるため、SSGの恩恵を受けられなくなる。トップページのリダイレクトのためだけに、高速化のメリットを捨てるのは非効率的である。また、Next.jsの新しいバージョンであるApp RouterではgetServerSidePropsが利用できなくなるため、将来的な互換性も考慮すると、これも最適な解決策とは言えなかった。
そして最終的に見つけた最も適切な解決策は、Next.jsの「ミドルウェア(Middleware)」機能を利用することであった。ミドルウェアとは、サーバーにリクエストが届いて、そのリクエストに対するページの処理が始まる「前」に、特定の処理を挟み込むことができる機能だ。これにより、ページが実際にレンダリングされる前に、リクエストのパスをチェックしたり、ユーザー認証の状態を確認したり、そして今回の要件のようにリダイレクトを行ったりすることができる。
ミドルウェアを実装するには、プロジェクトのルートディレクトリ、またはsrcディレクトリの直下にmiddleware.ts(あるいはmiddleware.js)という名前のファイルを作成する。このファイルの中で、リクエストオブジェクトを受け取り、レスポンスを返す関数を記述する。関数内では、リクエストされたパスがトップページを示す/であるかどうかを判断し、もしそうであればNextResponse.redirect()というメソッドを使って、指定した別のページへリダイレクトするよう指示を返す。
ミドルウェアを活用する際の重要なポイントがいくつかある。一つは、NextResponse.redirect()を使用することだ。これはNext.jsが提供するヘルパー関数で、リダイレクト処理を簡単に行うことができる。もう一つは、config.matcherという設定を利用することだ。ミドルウェアはすべてのリクエストに対して実行されるため、何も設定しないとWebサイトのどんなパスへのアクセスでもミドルウェアの処理が走ってしまう。これは無駄な処理を増やし、パフォーマンスに影響を与える可能性がある。config.matcherを使用することで、「このミドルウェアは、特定のパスパターンに合致するリクエストの場合にのみ実行する」というように、対象とするパスを限定できる。今回のケースでは、トップページである/へのリクエストと、リダイレクト先である/home(仮称)のようなパスを対象外にする設定を行う。
リダイレクトループを防ぐことも非常に重要である。もし/へのアクセスを/homeへリダイレクトするように設定したとして、その/homeへのアクセスもミドルウェアの対象に含まれていると、/homeへリダイレクトされた後、再びミドルウェアが/homeを検出して別の場所へリダイレクトしようとし、無限ループに陥ってしまう可能性がある。これを避けるためには、config.matcherの設定で、リダイレクト先のパスをミドルウェアの処理対象から除外する必要がある。例えば、/へのリクエストのみを対象とし、/homeを含まないように設定する。これにより、/homeへリダイレクトされた後にはミドルウェアが介入せず、正常に/homeページが表示されるようになる。
まとめると、Next.jsでトップページ(/)から別のページへリダイレクトしたいという要件に対しては、next.config.jsのredirectsやgetServerSidePropsにはそれぞれデメリットや限界があるため、サーバーへのリクエストがページの処理に入る前に介入できる「ミドルウェア」機能を利用するのが最も効果的かつ推奨される解決策である。ミドルウェアを使うことで、クライアントサイドからのナビゲーションを含むあらゆる経路からのトップページへのアクセスを検知し、パフォーマンスへの影響を最小限に抑えつつ、確実に指定のページへリダイレクトさせることができる。特にconfig.matcherを活用してミドルウェアが適用されるパスを適切に設定し、リダイレクトループを避ける工夫をすることが、安定した動作のために不可欠である。この経験から、Next.jsで特定の振る舞いをアプリケーション全体で制御したい場合、ミドルウェアが非常に強力なツールとなることを改めて認識した。