はじめに
Next.jsのApp Routerはプロジェクトの構造をappディレクトリ内でファイル名とフォルダ名とその組み合わせを元にして決定します。
この記事ではNext.jsのv15.1.0から新たに追加された2つの予約されたファイル名と2つの機能を紹介します。
執筆現在v15.0.4-canary.33でcanaryとして存在しています。そのためこれから紹介する機能を利用するにはexperimental.authInterruptsをtrueに設定する必要があります。
const nextConfig: NextConfig = {
experimental: {
authInterrupts: true,
},
};
追加された機能を利用して作成したデモページを作成しました。実際に触りたい場合はこちらをどうぞ。
forbidden
forbidden.jsはnot-found.jsと同じような機能を持つファイルです。同時に追加されたforbidden関数と合わせて権限の不足等のエラー時に利用されます。
ページのUIの作成中にfobiddenが呼び出された時、そのセグメントのpage.jsではなく、403エラーと合わせてforbidden.jsに記述されたUIが表示されます(forbidden.jsがなければNext.jsが用意したデフォルトのUIが表示されます)。
import { forbidden } from 'next/navigation'
import { getUser } from '@/model/user'
export default async function CreateBlog() {
const user = await getUser()
// ブログを作成・編集する権限がなければforbiddenへ移動
if (!hasWriteBlogPermission(user.permissions)) {
// returnは不要
forbidden()
}
// 通常表示されるUI
return (
<main>
<CreateBlogForm />
</main>
)
}
forbidden関数がサーバーアクション、ルートハンドラ内で実行された場合は、処理を中断してステータスコード403を返します。
'use server'
import { forbidden, notFound } from 'next/navigation'
import { getUser } from '@/model/user'
import { getBlog, updateBlog } from '@/model/blog'
export async function update(formData: FormData) {
const user = await getUser()
const blog = await getBlog(formData)
// ブログがない場合は404を返す
if (!blog) {
notFound()
}
// ブログを記述したユーザーでない場合は403を返す
if (blog.userId !== user.id) {
forbidden()
}
// ブログの更新処理
// ...
}
unauthorized
unauthorized.jsもまたunauthorized関数と合わせて未ログイン等のエラー時に利用されます。
ページのUIの作成中にunauthorizedが呼び出された時、そのセグメントのpage.jsではなく、401エラーと合わせてunauthorized.jsに記述されたUIが表示されます(unauthorized.jsがなければNext.jsが用意したデフォルトのUIが表示されます)。
import { unauthorized } from 'next/navigation'
import { getUser } from '@/model/user'
export default async function CreateBlog() {
const user = await getUser()
// ログインしていない場合はunauthorizedへ移動
if (!user) {
// returnは不要
unauthorized()
}
// 通常表示されるUI
return (
<main>
<CreateBlogForm />
</main>
)
}
unauthorized関数はサーバーアクション、ルートハンドラ内で実行された場合は、処理を中断してステータスコード401を返します。
'use server'
import { unauthorized, forbidden, notFound } from 'next/navigation'
import { getUser } from '@/model/user'
import { getBlog, updateBlog } from '@/model/blog'
export async function update(formData: FormData) {
const user = await getUser()
// ログインしていない場合は401を返す
if (!user) {
unauthorized()
}
// ブログの更新処理
// ...
}
さいごに
Next.jsのcanaryで2つのFile Conventionsが追加され、それに関連する2つのnavigationAPIを紹介しました。
今後も新たな意味を持つファイル名が追加されると考えられるので、現存しないファイル名であっても_を先頭につけるように心がけて行きたいです。