TL;DR
-
next export
は他のウェブフレームワークと違い、単一のhtmlではなくpages
単位でhtmlを書き出す - そのため、一般的なSPA向けのサーバー設定では、ブラウザの更新時に404が発生してしまう
- これを回避するには、
/
というパスへのリクエスト時に/index.html
、/hoge
なら/hoge.html
を探しに行く設定がwebサーバーに必要。下記はNginxの設定例。
location / {
root /hoge/fuga/html;
index index.html;
try_files $uri $uri.html $uri/ /404.html;
}
はじめに
これまでは一番経験があり安定して開発できる技術としてVue2を使ってきたのですが、EoLも見えてきてそろそろ乗り換え…ということで、Next.jsを使い始めました。このとき静的にアプリケーションを配信するためのコマンドnext export
が、これまで触ってきたSPA(たとえばVue)の挙動と違い、そのためwebサーバーの設定で少し困ったので、メモしておきます。
Vueのビルドと違うところ
Vueの場合index.htmlはひとつですが、next export
はpages
に配置されているコンポーネントの数だけhtmlが作成されます。SSG用のコマンドなので事前に全ページのHTMLを作成しておく、という思想なのでしょう。
たとえば
pages
├── _app.tsx
├── sample.tsx
└── index.tsx
こんな構造だと、next export
の結果は
dist
├── 404.html
├── _next
├── sample.html
└── index.html
こんな感じになるはずです。
困ったこと
上記でも、ローカルで開発している限りは、特に困ることがありません。しかしこのビルド結果をVueだとかと同じ感覚でデプロイすると(=単なるwebサーバーでの配信+index.htmlへのフォールバック)、ページリロード時に404となったり、トップページが表示されたりと、期待した挙動になりません。
期待した挙動にならない理屈
- CSRで
/sample
を表示しているとする - 更新すると、webサーバーは
sample
というファイルを探しに行く(が、存在しない) - 存在しないのでindex.htmlにフォールバックする(が、ページが
/sample
としてレンダリングされない!)
2まではVueのルーティングでも起こる問題ですが、3はNext.jsで発生する問題です。
Next.jsでは、/sample
を更新する際は/sample.html
を見に行かせる設定が必要となります。
Nginxの設定
下記のように設定することで、/hoge
というURLをリクエストして/hoge
が存在しなければ、/hoge.html
を探しに行かせることができます。また、/
へのリクエストは/index.html
に流す、という設定も必要です。下記が設定ファイルの例です(冒頭と同じ)。
location / {
root /hoge/fuga/html;
index index.html;
try_files $uri $uri.html $uri/ /404.html;
}
終わりに
インターネッツを探しても、あんまり記事が見つからなかったのですが、next exportをNginxで運用…というのはあんまりやるべきじゃないのでしょうか?
それとももっと良い方法がある?webサーバー+CSRがもう流行っていない?CRAを使うべき?
知見のある方はコメント頂けるとうれしいです。。。