Closed4

Next.js App Routerを使った実装で詰まったこと

MiyaboomMiyaboom

next.config.jsでページのCache-Controlヘッダーを設定できない

※Version 13.4.12時点

App RouterではCache-Controlヘッダーを内部的に上書きする。
MiddlewareやCustom Serverでレスポンスを書き換えようとしたがダメだった。

対処方法

今のところない。
困ってる人たくさんいそうなので、いずれ公式が対応してくれるかもしれない。

Custom Serverを使った検証例

server.js
/** 一部省略 */
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)
  })
})

参考

その他

Zenn記事のコメント

Node.jsのresをラップしたオブジェクトをNext.jsに渡せば対処できる

レスポンスヘッダーの変更を監視、またはres.setHeader()やres.send()をインターセプトしたらいけるかもしれない。ただ、ハック感が強いので深入りはやめておく。

MiyaboomMiyaboom

MSWが動かない

※Version 13.4.12時点

Next.jsがグローバルなfetchに干渉しているのが原因らしい(ちゃんとわかってない)

対処方法

MSWで何とかする方法は今のところない。
一旦MSWの使用は諦め、API Routesにモックサーバーを立てる等の対応が考えられる。

参考

MiyaboomMiyaboom

本番環境でだけ発生する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モジュールを使用している。
https://github.com/vercel/next.js/blob/v13.4.12/packages/next/src/server/lib/server-ipc/invoke-request.ts#L18
githubの議論によると13.4.7に下げると解消したという報告があるため、プロセス間通信以外でfetchを使っている場所で同様のエラーが発生するのかもしれない。

また、undiciで発生するエラーの対応はこちらDelete errorneous empty content length headerで進んでいる模様。

参考

このスクラップは5ヶ月前にクローズされました