not-found.tsx が効かないとき。404 の出し分け
not-found.tsx は、存在しない URL と notFound() を呼んだときとで、使われるものが違います。
どの not-found.tsx が使われるか
app/not-found.tsx と app/shop/not-found.tsx を置いて、URL を変えて開きました。
| 開いた URL | 出た画面 |
|---|---|
| /nope(どのページにも当たらない) | app/not-found.tsx |
| /shop/a/b(どのページにも当たらない) | app/not-found.tsx |
| /shop/zzz(shop/[id] のページが notFound() を呼ぶ) | app/shop/not-found.tsx |
/shop/a/b では、shop 用の not-found は使われませんでした。「shop 用に作ったのに出ない」は、たいていこの形です。
- Serverどのページにも当たらない URL
探しに行くページが無い。ルートの app/not-found.tsx だけが使われる。
- Serverページが notFound() を呼ぶ
呼んだ場所から上へ、一番近い not-found.tsx を探す。
公式ドキュメントも、当たらない URL をまとめて受け持つのはルートの app/not-found.tsx だと説明しています。
下の階層の not-found を使うには
notFound() を呼んだページから、上の階層へ一番近い not-found.tsx が使われます。実機では、同じフォルダ(app/blog/[id]/not-found.tsx)に置けばそれが、無ければひとつ上(app/shop/not-found.tsx)が使われました。
/shop/a/b のような当たらない URL にも shop 用の画面を出したいなら、受けるページを置いて、そこで notFound() を呼びます。
// app/shop/[...slug]/page.tsx
import { notFound } from 'next/navigation'
export default function Page() {
notFound()
}
実機で、この形なら /shop/a/b に app/shop/not-found.tsx が出ました。
置かないと英語の画面
not-found.tsx を1つも置かないと、Next.js の既定の画面が出ます。英語で「404」と「This page could not be found.」です。
日本語のサイトなら、app/not-found.tsx を置いて、トップや検索への案内を出してください。実機では、どの not-found もルートの layout の内側に出たので、ヘッダーやフッターはそのまま残ります。
// app/not-found.tsx
import Link from 'next/link'
export default function NotFound() {
return (
<div>
<p>ページが見つかりませんでした。</p>
<Link href="/">トップへ戻る</Link>
</div>
)
}
状態コードは 404 とは限らない
検索エンジンに「このページは無い」と伝えるのは、画面ではなく応答の状態コードです。実機で確かめました。
| 条件 | 状態コード | robots の noindex |
|---|---|---|
| loading.tsx が無い | 404 | 付く |
| 同じ階層に loading.tsx がある | 200 | 付く |
| どのページにも当たらない URL | 404 | 付く |
公式ドキュメントも、少しずつ送る応答(loading.tsx があるとき)では 200、そうでなければ 404 と説明しています。実機では、どの場合も noindex が付きました。
見つからないことはエラーではない
notFound() は、error.tsx ではなく not-found.tsx を出します。「無いものは無い」と伝えるもので、何度やり直しても結果は変わりません(エラー画面の作り方)。実際に動く形は見つからないときの最小構成にあります。
出典
- nextjs.org/docs/app/api-reference/file-conventions/not-found
- nextjs.org/docs/app/api-reference/functions/not-found
このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。