Vue.js を使用して開発したアプリケーションを本番環境にデプロイした際、history モードを利用していると、ページをリロードしたときに 404 エラーが発生することがよくあります。これは、クライアントサイドルーティングで生成された URL に対して、サーバー側が対応する静的ファイルを返せないために起こります。以下では、Vue プロジェクトと Nginx の設定を調整することでこの問題を解決する手順を説明します。
原因の概要
vue-router の history モードは URL からハッシュ(#)を除去し、よりクリーンなパス形式(例: /dashboard)を実現します。しかし、この形式の URL は実際のファイルやディレクトリに対応していないため、ユーザーが直接アクセスしたりページをリロードしたりすると、Web サーバー(例: Nginx)は該当するリソースが存在しないと判断して 404 を返します。
解決手順
1. 環境変数の設定(.env.production)
プロジェクトルートに .env.production ファイルを作成または編集し、アプリケーションのベースパスとパブリックパスを定義します。ここでは、アプリが /admin-panel というサブパスで配信されると仮定します。
VUE_APP_BASE_PATH=/admin-panel
PUBLIC_PATH=http://example.com/admin-panel
2. Vue Router のベースパス設定
src/router/index.js(または該当ファイル)で、ルーターの base オプションを環境変数に基づいて設定します。
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(process.env.VUE_APP_BASE_PATH || '/'),
routes: [...],
})
3. vue.config.js のパブリックパス設定
静的アセットの参照先を正しくするために、vue.config.js に以下の設定を追加します。
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? process.env.PUBLIC_PATH
: '/',
}
4. Nginx の設定
Nginx の設定ファイル(例: /etc/nginx/sites-available/default)で、対応する location ブロックを追加します。静的ファイルは /var/www/html/admin-panel に配置されていると仮定します。
location /admin-panel {
alias /var/www/html/admin-panel;
try_files $uri $uri/ /admin-panel/index.html;
}
try_files により、存在しないパスへのリクエストも index.html にフォールバックされ、Vue Router がクライアント側で適切にルーティングを処理できます。
5. ビルドとデプロイ
以下のコマンドで本番ビルドを実行し、生成された dist ディレクトリの内容を Nginx の対応ディレクトリにコピーします。
npm run build
# または、スクリプト名が異なる場合はそれに従う(例: npm run build:prod)
その後、Nginx の設定を検証して再読み込みします。
nginx -t
nginx -s reload
これにより、history モードを使用した Vue アプリケーションでも、ページリロード時に 404 エラーが発生しなくなります。