🫠

Cloud RunでだけNext.jsのParallel Routesが動かなくなるのは、URLが勝手にデコードされているから

に公開

想定している状況

npm run devしても、npm run buildからのnpm run startしても、docker build .からのdocker run -p 3000:3000しても大丈夫なのに、Cloud Runにデプロイしたときだけ、parallel routesを開くとこうなる。
Application error: a client-side exception has occurred while loading マスクされた文字 (see the browser console for more information).

開発者ツールで確認してみるとUncaught ChunkLoadError: Loading chunk [number] failed.となっており、layoutやpageのチャンクファイルが404で読み込めていない。
Chromeの開発者ツールで、layout-7b51de46...が404 Not Foundになっているスクショ

解決策

Middlewareにこれを書く(書き足す)。

const exactUrl = request.url.replaceAll("@", "%40");
if (exactUrl !== request.url) {
  return NextResponse.rewrite(exactUrl);
}
return NextResponse.next();

解説

Middlewareでrequest.urlを出力した状態で、ローカルの環境と、Cloud Run環境を比較してみると、こうなっている。

ローカル

url: 'http://localhost:3000/_next/static/chunks/app/hoge/%5Bfuga%5D/%40piyo/hogehoge/hogefuga/page-xxxxxxxxxxxxx.js'

Cloud Run

url: 'https://localhost:3000/_next/static/chunks/app/hoge/%5Bfuga%5D/@piyo/hogehoge/hogefuga/page-xxxxxxxxxxxxx.js'

Cloud Runでだけ、@%40)がデコードされている。[]%5B%5D)はそのままなのに……

実は、既知の問題としてGoogle Cloudのドキュメントには書いてある。
https://cloud.google.com/run/docs/known-issues?hl=ja#url-decode

全部の文字が対象でないのが厄介で、とにかくエンコードし直せば良いというわけでもない。
ただ、具体的な文字のリストは公開されていないので、事前に開発環境で試してみて、@以外にも対象の文字があれば追記する必要がありそう。
(多分。もし何らかの法則をご存知の方がいれば教えてください)

Discussion