NextJs 的 404 handling

主要討論在 app router 使用情境

使用 /src/app/[...others] 處理

即建立 /src/app/[...others]/page.tsx 檔案,內容類似這樣

import { redirect } from "next/navigation";

export default async function NotFound() {
    // Redirect to your custom 404 page
    redirect("/404");
}

這樣可以讓所有找不到頁面的 request 全部轉址導向 /404 頁面,因此在來編輯 /src/app/404/page.tsx, 類似

import React from 'react';

const Custom404 = () => {
  return (
    <div>
      <h1>404 - Page Not Found</h1>
      <p>The page you're looking for doesn't exist.</p>
    </div>
  );
};

export default Custom404;

使用 not-found.tsx

即建立 /src/app/not-found.tsx, 內容類似這樣

import type { Metadata } from "next";

export default function Custom404() {
    return (
        <div id="notfound-404">
        <h1>404 - Page Not Found!!</h1>
        <p>The page you&apos;re looking for doesn&apos;t exist.</p>
        </div>
    )
}

export const runtime = 'edge';
export const dynamic = 'force-dynamic';
export const revalidate = 0;

export const metadata: Metadata = {
    title: '404 - Page Not Found',
    description: 'The requested page could not be found.',
};

兩者差異

如果開啟瀏覽器開發人員工具,檢視 Network panel, 會發現當瀏覽一個不存在的頁面時(e.g. http://localhost/login/indexxxx ), 用 not-found.tsx 的其處理行為會是發現該頁面不存在,就直接執行 not-found.tsx 內容並輸出回傳,所以 request login/indexxxx 直接就是http status 404.

若是用 [...others] 這樣的 catch-all dynamic routes, 則會經過一次 307 redirect 才會到 404 頁面。所以不是直接回傳 404 http status code 給瀏覽器。

比較正確的用法應該是 not-found.tsx