概要
- Next.jsの本番環境用ロギング設定に苦労した体験談
- ミドルウェアの制限とAsyncLocalStorageの挙動の問題点
- ヘッダー経由でしか情報を渡せないNext.jsの設計上の課題
- カスタムサーバー導入でも根本的な改善は困難
- SvelteKitなど他フレームワークとの比較とNext.jsへの批判
Next.jsでの本番ロギング地獄
- Next.js サービスで障害発生、本番環境でのログ取得困難
- デフォルトのロギングは 開発環境のみ 有効
- pino ライブラリを選択し、ミドルウェアで導入を試みる
- ミドルウェアは 4つのパラメータ しか渡せず、 ヘッダーのみ がルートに影響
- 複数ミドルウェア や チェーン 不可という設計上の制約
- AsyncLocalStorage を利用し、リクエストごとのloggerインスタンス生成
- ログ出力はできるが、 Edge Runtime のため意図した挙動と異なる
- Node.js Runtime に切り替えると一部動作するが、プロジェクトによっては不安定
ページ・レイアウトでのロギング問題
- ページやレイアウトでlogger利用時、 nullが返る 問題発生
- ミドルウェアと 非同期コンテキスト が一致せず、loggerが共有されない
- 唯一渡せる情報が ヘッダー のみのため、requestIdをヘッダー経由で伝搬
- サーバ・ミドルウェア・クライアントで ロギング実装を分割 する必要性
- import制限 により、サーバ/ミドルウェア間でloggerコード共有不可
カスタムサーバー導入と挫折
- custom server で独自のロジック実装を試みる
- AsyncLocalStorage を再利用し、サーバ・ミドルウェア・ページでlogger呼び出し
- しかし 非同期コンテキストの継続性 が保証されず、loggerが機能しない
- headers() や cookies() はAsyncLocalStorageを使っているが、ユーザーは同じ方法が使えない
- ミドルウェアからページへ情報を渡す手段は ヘッダー か リダイレクト のみ
Next.js設計への批判と他フレームワーク比較
- Next.js 開発者の「ビジョン」による制約の多さ
- 日常的に遭遇する「痛み」と ユーザー体験の悪化
- Vercel 製の SvelteKit では、
event.localsで自由にオブジェクトやクラスを渡せる - 複数handle関数 や シーケンス実行 も可能
- SvelteKit の柔軟性とNext.jsの硬直性の対比
- Vercel 自身のフラグシップでこの差は納得できないという不満
まとめ・教訓
- Next.js の本番ロギングは設計上非常に困難
- ミドルウェアの貧弱さ、 AsyncLocalStorage の制約、情報伝搬手段の乏しさ
- SvelteKit など、より柔軟なアプローチを持つフレームワークの存在
- Vercel はNext.jsの改善に本腰を入れるべきという提言
- この経験が、より良いフレームワーク選択や設計への気づきとなる