主要討論在 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're looking for doesn'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