Dynamic server usage の読み方と消し方
実際に出るエラー
cookies などを try で囲んだときに、ビルドのログに出る文言です。
いつ出るのか
cookies() のように開いた人ごとに違うものを読むところを、try で囲むと出ます。
import { cookies } from 'next/headers'
export default async function Page() {
let theme = 'light'
try {
theme = (await cookies()).get('theme')?.value ?? 'light'
} catch (e) {
console.error('caught:', e) // ここがビルドのログに出す
}
return <p>theme={theme}</p>
}
実機で、ビルドは通り、ログに caught: Error: Dynamic server usage: … と出ました。付いていた digest は DYNAMIC_SERVER_USAGE です。
ページは壊れていない
赤い Error に見えますが、実機ではページは動いていました。
- ビルドの一覧で、このページは ƒ(開かれるたびに描く)だった
- 開くと、Cookie に theme=dark を送れば dark、送らなければ light を表示した
- 開いたときのサーバーのログには、何も出なかった
Cookie はビルドのときには読めません。Next.js は cookies() が呼ばれた時点で合図を投げて描くのをやめ、そのページを「開かれるたびに描く」扱いにします。try で囲むと、その合図が自分の catch に届いてしまう。ログに出ていたのはそれです。
消し方
try の外で読む
Cookie を読むところは try の外に出し、try の中は自分の処理だけにします。
export default async function Page() {
const store = await cookies() // try の外
let name = 'guest'
try {
name = await loadProfile() // 外部の API など、自分の処理だけ
} catch (e) {
console.error(e)
}
return <p>{store.get('theme')?.value} {name}</p>
}
実機で、ログに Dynamic server usage は出なくなり、ページは ƒ のままでした。
囲むなら unstable_rethrow で投げ直す
囲む範囲を変えられないときは、catch の先頭で next/navigation の unstable_rethrow を呼びます。Next.js の合図なら投げ直し、それ以外なら何もしません。
import { unstable_rethrow } from 'next/navigation'
try {
theme = (await cookies()).get('theme')?.value ?? 'light'
} catch (e) {
unstable_rethrow(e)
console.error(e)
}
実機で、ログに出なくなりました。公式ドキュメントによると、redirect や notFound の合図も同じように投げ直します。
似た文言:dynamic = 'error'
ページに export const dynamic = 'error' を付けていると、別の文言でビルドが止まります。
Error: Route / with `dynamic = "error"` couldn't be rendered statically because it used `cookies()`.
'error' は「ビルドのときに描けないものを使ったら止める」という指定です。Cookie を使うと決めたなら外します(Next.js のキャッシュ)。
まとめ
- Dynamic server usage は、Next.js の合図を自分の catch が拾ったもの。ページは動いている
- Cookie などは try の外で読む。囲むなら catch の先頭で
unstable_rethrow(e) dynamic = 'error'の文言は別物。付けた指定を外す
出典
- nextjs.org/docs/messages/dynamic-server-error
- nextjs.org/docs/app/api-reference/functions/unstable_rethrow
- nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。