Next.jsでリダイレクトを行う方法をまとめてみた

6 min read読了の目安(約5600字

この記事について

この記事では、Next.jsのリダイレクト処理をまとめた記事になります。
Next.jsの基本的な理解がある事を前提に解説してきますので、予めご了承ください。

想定する環境

package.json
  "dependencies": {
    "next": "10.2.0",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },

getStaticProps・getServerSidePropsを使う場合

getStaticPropsgetServerSidePropsのリダイレクトは、両方とも同じようにできますので、以下の例ではgetServerSidePropsのコードのみ記述します。

サーバー側でリダイレクト処理を行いたい場合は、この方法が便利です。

サーバー側で実行されるので、Cookieを用いた処理やDBとの連携が可能となっていますが、リダイレクトの処理はどうしても遅くなってしまう傾向にあるので、ユーザー体験を求めないページ(認証が必要なページなど)に使用する事をオススメします。

./pages/any_page.tsx
import { GetServerSideProps } from 'next'

export const getServerSideProps: GetServerSideProps = async () => {
  return {
    redirect: {
      permanent: false, // 永続的なリダイレクトかどうか
      destination: '/redirect_page_url', // リダイレクト先
      // destination: 'https://example.com/' // 別サイトでも指定可能
    },

    // ステータスコードを変更する場合は、`permanent`の代わりに`statusCode`を使用します。
    redirect: {
      statusCode: 302, // ステータスコード指定
      destination: '/redirect_page_url', // リダイレクト先
    },    
  }
}

オプション

また、redirectに設定できる値は以下の通りです。

export type Redirect =
  | {
      statusCode: 301 | 302 | 303 | 307 | 308 // ステータスコード
      destination: string // リダイレクト先のURL
      basePath?: false    // `basePath`を無効にします
    }
  | {
      permanent: boolean  // 永続的なリダイレクト化のフラグ
      destination: string // 同上
      basePath?: string   // 同上
    }

// basePathについては以下を参照してください👇
// https://nextjs.org/docs/api-reference/next.config.js/basepath

参照

詳しい挙動は、以下のファイルから確認できます👇

https://github.com/vercel/next.js/blob/c922c6a3f4d4e463cce4713d9cf8f61c13b3fac8/packages/next/build/webpack/loaders/next-serverless-loader/page-handler.ts

getInitialPropsを使う場合

サーバー・クライアント両方の環境でリダイレクト処理を行いたい時には、この方法が便利です。

実装は複雑になってしまいますが、他の方法よりも体験の良いリダイレクトを行えるため、ユーザー体験を求めるページなどで使用すると良いと思います。

./pages/any_page.tsx
import { NextPage } from 'next'
import Router from 'next/router'

const RedirectPage: NextPage = () => {/* -- 省略 -- */}

RedirectPage.getInitialProps = async ({ res }) => {

  // サーバー側でリダイレクト
  if (typeof window === 'undefined') {
    res.writeHead(302, { Location: '/redirect_page_url' })
    res.end()

    return {} // 空オブジェクトだと警告文が発生するので注意してください!
  }

  // クライアント側でリダイレクト
  Router.push('/redirect_page_url')

  return {} // 同上
}

export default RedirectPage

useEffectを使う場合

SPAなどでリダイレクト処理をしたい場合や、Firebase Authなどのようなサービスと連携する必要がある場合は、この方法が使えます。

クライアント側でリダイレクト処理を行えるため、クライアントの状態を使ったリダイレクトが簡単に実装でき、比較的速いリダイレクトができます。

しかし、サーバー側との連携が必要な場合は少し工夫する必要があったり、useEffect()の仕様上、一度描画されてしまうので、ちょっと見栄えが悪くなる可能性があります。

./pages/any_page.tsx
import { NextPage } from 'next'
import { useRouter } from 'next/router'

const RedirectPage: NextPage = () => {
  const router = useRouter()

  useEffect(() => {
    router.replace('/redirect_page_url') // ここでリダイレクト
  }, [])

  return null
}

実装例

より具体的な実装例は、以下の記事が参考になります👇

https://zenn.dev/catnose99/articles/2169dae14b58b6#未ログインならリダイレクトするサンプル

設定ファイルを使ってリダイレクト

next.config.jsredirectsを設定する事でもリダイレクト処理を実装できます。

この方法ではページコンポーネントを必要としないので、ページに左右されないリダイレクトを行いたい時に便利です✨

next.config.js
/** @type {import('next/dist/next-server/server/config-shared').NextConfig} */
const config = {
  async redirects() {
    return [
      {
        source: '/about', // リダイレクト元のURL
        destination: '/redirect_page_url', // リダイレクト先のURL
        permanent: true, // 永続的なリダイレクトかのフラグ
      },
    ]
  },
}

module.exports = config

オプション

また、指定できるオプションは以下の通りです👇

type Redirect = {
    source: string;      // リダイレクト元のパス文字列
    destination: string; // リダイレクト先のパス文字列
    basePath?: false;    // `basePath`を無効にします
    locale?: false;      // localeをマッチング時に含めないかのフラグ
    has?: RouteHas[];    // header, cookie, queryなどにマッチするための配列
    statusCode?: number; // ステータスコード
    permanent?: boolean; // 永続的なリダイレクトかのフラグ
};

// basePathについては以下を参照してください👇
// https://nextjs.org/docs/api-reference/next.config.js/basepath

// `has`オプションの型
export type RouteHas = {
    type: 'header' | 'query' | 'cookie';
    key: string;
    value?: string;
} | {
    type: 'host';
    key?: undefined;
    value: string;
};

参考

https://nextjs.org/docs/api-reference/next.config.js/redirects

https://zenn.dev/jay_es/articles/2021-04-22-config-js

結局、どれを使えばいいのか?

及ばせながら、筆者の知見をまとめると以下のようになります👇

方法名 遷移時の体験の良さ 実装のしやすさ 自由度
getServerSideProps
getStaticProps
useEffect
getInitialProps
設定ファイル

上記の表より、

ユーザー体験を求めない場合

  • getServerSideProps
  • getStaticProps

ユーザー体験を求める場合

  • getInitialProps

簡単に実装したい場合

  • useEffect

ページなどに関係なく処理したい場合

  • 設定ファイル( next.config.js )

となります。

作るプロダクト、サーバーの状況、実装方法によって変わってくるとは思いますが、参考程度に思って頂ければ幸いです。

その他の参考リンク

https://developer.mozilla.org/ja/docs/Web/HTTP/Redirections

https://github.com/vercel/next.js/discussions/14890

あとがき

ここまで読んでくれてありがとうございます🙏

記事に間違いなどがあれば、コメントなどで教えて頂けると嬉しいです。

これが誰かの参考になれば幸いです。

それではまた👋