NginxでHistory APIルーティングを支える設定テクニック

シングルページアプリケーション(SPA)のURLには、ハッシュ(#)を使う方法と、History APIを使う方法の2種類があります。前者はブラウザのサポートが万全で、サーバ側の設定不要という利点がありますが、URLに「#」が含まれるため見た目がやや野暮ったいです。後者はURLがクリーンでSEOにも有利ですが、ブラウザをリロードした際に404が返るという落とし穴があります。

この記事では、History APIルーティングを採用したSPAをNginxでホスティングする際に、404を回避するための設定を解説します。

locationディレクティブの動作原理

Nginxの設定ファイル内で、httpserver ブロックの中に記述する location は、リクエストURIごとに処理を振り分ける役割を担います。

location [修飾子] パターン {
    # 処理
}

修飾子には次の4種類があり、優先順位が定められています。

  1. = … 完全一致が最優先
  2. 修飾子なし … 前方一致でより長いパスが優先
  3. ^~ … 前方一致だが正規表現より優先
  4. ~(大小区別あり)/~*(大小区別なし) … 正規表現マッチ

try_filesで「ファイルが無いときのフォールバック」を実現

History APIルーティングを使うと、https://example.com/article/123 のようなパスにアクセスしても、実際のファイルシステムには article/123 というディレクトリやファイルは存在しません。Nginxはデフォルトで「ファイルが無い → 404」を返すため、リロードするとエラー画面が表示されます。

これを回避するには try_files を使います。

server {
    listen 80;
    server_name example.com;

    root /var/www/app/dist;

    location / {
        # 1. ファイルが存在すれば返す
        # 2. ディレクトリが存在すれば返す
        # 3. 両方とも存在しなければ /index.html を返す
        try_files $uri $uri/ /index.html;
    }

    # 静的アセットは長期キャッシュ
    location ~* \.(js|css|png|jpg|svg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

上記設定により、/article/123 にリロードしても index.html が返され、クライアント側のルーターが該当画面を描画します。

aliasでパス差分を吸収するケース

ビルド成果物を /var/www/app/dist に配置しているのに、URL上は /app/ 配下で配信したい場合、alias を使ってパスをマッピングします。

location /app/ {
    alias /var/www/app/dist/;
}

alias の末尾にスラッシュを付ける/付けないで挙動が変わるため注意が必要です。

動作検証手順

  1. nginx -t で設定ファイルの構文チェック
  2. nginx -s reload で設定を反映
  3. ブラウザで直接 /any/path を開き、404にならないことを確認
  4. 開発者ツールの Network タブで index.html が返却されていることを確認

タグ: nginx SPA history-api try_files location

5月28日 19:55 投稿