[Cloudflare Pages + Next.js] Dynamic Routes利用時にリロードすると404エラーになるときの対処法

2023.05.19

どうも!オペレーション部の西村祐二です。

Next.jsのDynamic Routesを利用時したアプリケーションをCloudflare Pagesにデプロイしたときに、Dynamic Routesのpath上でリロードすると404エラーとなってしまう現象に遭遇したので、その対処法をブログにまとめておきます。

Routing: Dynamic Routes | Next.js

最初に結論

public配下に_redirectsを配置しておくことで、この現象を回避できました。

_redirectsの例

/users/:id /users/[id] 200

Cloudflare Pagesでは下記のように_redirectsに記載されたルールに基づいてリダイレクトしてくれる機能があるのでこれを利用します。

 [source] [destination] [code?]

Redirects · Cloudflare Pages docs

試してみる

ハマった現象を再現するように環境を構築していきます。

環境

  • Next,js: 13.4.2
  • Node.js: v18.15.0
  • wrangler: 2.15.0
  • @cloudflare/next-on-pages: 0.8.0

Next.jsの雛形プロジェクト作成

npx create-next-app --ts test-dynamic-routing

今回、設定は下記のようにしています。
✔ Would you like to use ESLint with this project? … Yes
✔ Would you like to use Tailwind CSS with this project? … Yes
✔ Would you like to use `src/` directory with this project? … Yes
✔ Would you like to use experimental `app/` directory with this project? … No
✔ What import alias would you like configured? … @
cd test-dynamic-routing

Dynamic Routesを利用したページ追加

ユーザの情報を表示するページを想定して、

src/pages/users/[id].tsxのファイルを作成しておきます。

画面はURLから取得したidを表示しているだけです。

src/pages/users/[id].tsx

import { useRouter } from "next/router";

export default function User() {
  const router = useRouter();
  const { id } = router.query;
  console.log(id);
  return (
    <div>
      <p>{id}</p>
    </div>
  );
}

あとは、ホーム画面から/users/hogeにページ遷移できるリンクを配置しておきます。

src/pages/index.tsx

import Image from 'next/image'
import { Inter } from 'next/font/google'
import Link from 'next/link'

const inter = Inter({ subsets: ['latin'] })

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <Link href="/users/hoge">
          /users/hoge
        </Link>
...

修正はこれで終了です。

ローカルで動作確認

ローカルで動作確認して、ローカルでは正常に画面が表示されることを確認します。

ホーム画面に配置したリンクをクリックし/users/hogeに遷移したあと、ブラウザリロードしても正常に画面表示されるかと思います。

npm run dev

Cloudflare Pagesにデプロイ

$ npx @cloudflare/next-on-pages
.
.
.
▲ Build Completed in .vercel/output [10s]
⚡️ Building Completed.
⚡️ Generated '.vercel/output/static/_worker.js'.

下記コマンドを実行して、プロジェクトなどを指定してCloudflare Pagesにデプロイしていきます。

$ wrangler pages publish .vercel/output/static

✔ Select an account › 
✔ Enter the name of your new project: … your project name
✔ Enter the production branch name: … main

.
.
.

✨ Deployment complete! Take a peek over at https://<your url>

リロードすると404の画面が表示されることを確認

Cloudflare Pagesにデプロイが完了したらアクセスできるURLが発行されるので、アクセスします。

ホーム画面のリンクから画面遷移すると正常に画面が表示されますが

遷移した/users/hogeや他のpathでリロードすると404の画面が表示されることを確認できるかと思います。

正常に画面表示されるように修正

エラーの原因としてURLに指定された値に対応するファイルがないため404になってしまいます。なので、ビルド時に生成されたDynamic Routesのファイルにリダイレクトしてあげることによって正常に処理されるようにします。

リダイレクトはCloudflare Pagesの機能を使って実現します。

:idはプレースホルダーとなっています。詳細はドキュメントを確認ください。

public配下に下記_redirectsを配置して、再デプロイします。

_redirects

/users/:id /users/[id] 200

これで、Cloudflare Pages上でもリロードしても正常に画面が表示されるようになりました

さいごに

Next.jsのDynamic Routesを利用時したアプリケーションをCloudflare Pagesにデプロイしたときにハマったことと、その対応策をご紹介しました。

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