Next.js App Routerを使った実装で詰まったこと
next.config.jsでページのCache-Controlヘッダーを設定できない
→ (2024/11/20更新) 最新バージョン(v14.2.13)では設定できるようになっている
===
※Version 13.4.12時点
App RouterではCache-Controlヘッダーを内部的に上書きする。
MiddlewareやCustom Serverでレスポンスを書き換えようとしたがダメだった。
対処方法
今のところない。
困ってる人たくさんいそうなので、いずれ公式が対応してくれるかもしれない。
Custom Serverを使った検証例
/** 一部省略 */
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer(async (req, res) => {
// このCache-Controlヘッダーは無効
res.setHeader('Cache-Control', 'max-age=60, stale-while-revalidate=60')
// app.getRequestHandler()内部でCache-Controlヘッダーを上書きしてレスポンスを返している
await handle(req, res, parsedUrl)
})
})
参考
- Setting Cache-Control Header in NextJS App Router
- Cache-Control headers set in next.config.js are overwritten
- 最小限の gssp → App Router 移行パターン集
その他
Node.jsのresをラップしたオブジェクトをNext.jsに渡せば対処できる
レスポンスヘッダーの変更を監視、またはres.setHeader()やres.send()をインターセプトしたらいけるかもしれない。ただ、ハック感が強いので深入りはやめておく。
MSWが動かない
→(2024/11/20更新) NextのHMRのバグがブロッカーになっているが、対応は進んでいる模様 https://github.com/mswjs/msw/issues/1644#issuecomment-2433234922
==
※Version 13.4.12時点
Next.jsがグローバルなfetchに干渉しているのが原因らしい(ちゃんとわかってない)
対処方法
MSWで何とかする方法は今のところない。
一旦MSWの使用は諦め、API Routesにモックサーバーを立てる等の対応が考えられる。
参考
本番環境でだけ発生するundiciのエラー
※Version 13.4.13時点
本番環境で以下のようなエラーが発生することがある
TypeError: fetch failed
at Object.fetch (/app/node_modules/next/dist/compiled/undici/index.js:1:26669)
at async invokeRequest (/app/node_modules/next/dist/server/lib/server-ipc/invoke-request.js:21:12)
at async requestHandler (/app/node_modules/next/dist/server/lib/start-server.js:336:33)
at async Server.<anonymous> (/app/node_modules/next/dist/server/lib/start-server.js:152:13) {" cause: RequestContentLengthMismatchError: Request body length does not match content-length header
at write (/app/node_modules/next/dist/compiled/undici/index.js:1:67105)
at _resume (/app/node_modules/next/dist/compiled/undici/index.js:1:66726)
at resume (/app/node_modules/next/dist/compiled/undici/index.js:1:65413)
at connect (/app/node_modules/next/dist/compiled/undici/index.js:1:65301) {
code: 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH'
}
}
Next.js内部のプロセス間通信でfetchを使用しており、そのポリフィルの実装でundiciを使用している。
Content-Length:0
がヘッダーに付与されたGETリクエストを受け取るとundiciでRequestContentLengthMismatchError
が発生する。(私の場合)このGETリクエストはおそらくbotやCDNのヘルスチェックによるもので、本番環境でのみ発生したのはそのためと思われる。
対処方法(※未検証)
13.4.12にバージョンを下げる。
13.4.12以前は、プロセス間通信でfetchではなくnode標準のhttpモジュールを使用している。
githubの議論によると13.4.7に下げると解消したという報告があるため、プロセス間通信以外でfetchを使っている場所で同様のエラーが発生するのかもしれない。
また、undiciで発生するエラーの対応はこちらDelete errorneous empty content length headerで進んでいる模様。
参考
middlewareでrouteごとにCache-Controlを設定できるようになったらしいので要調査
Next.js App Router で route 毎に Cache-Control を任意に指定したいときは middleware を使う(今のところ