Vue.jsでアプリ開発を行っていくとき、vue-routerを導入してSPAを実装するケースがあると思います。
いざ開発したアプリをウキウキ気分でサーバにデプロイしたあとに動作確認してたら、
トップページ以外でリロードしたら404になるという現象に直面したことありませんか?
今回はその解決方法をまとめていきます。
原因と解決
解決方法だけを知りたい人のために先に原因と解決方法をまとめます。
原因:historyモードをHTML5モードにしてるから
トップページからページ遷移したときは問題なくアクセスできるのに、ページリロードや直接URL入力してアクセスしたときに404になってしまう原因は「routes/index.js」に設定しているhistoryをHTML5モードにしてることが原因です。
これによりページリロードや直接URL入力したアクセスの際にindex.htmlを経由しないため404となってしまいます。
※ historyがHashモードであればこの問題は発生しません。
解決:サーバにリダイレクト設定を適用する
ただ、URLに「#(ハッシュ)」が入るHashモードは使いたくないので利用するサーバにリダイレクト設定を適用します。
Apacheの場合
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
利用しているサーバで.htaccessの利用が有効な場合は上記の設定を.htaccessに記述し、設定適用します。
Nginxの場合
location / {
try_files $uri $uri/ /index.html;
}
サーバがNginxの場合は、設定ファイル(例として、default.conf)に上記設定を記述し、適用します。
Firebaseの場合
{
"hosting": {
"public": "dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Firebaseのhostingを使ってアプリを公開している場合は、既存のfirebase.jsonに上記のrewritesの設定記述を追記し、デプロイして設定を適用します。
その他のサーバ
Expressなどその他のサーバへの設定方法については、Vue Routerの公式サイトを参考にしてもらえればと思います。
参考リンク:Vue Router公式サイト
ページリロードで404になる原因を考える
ここからはHTML5モードでページリロードや直接URL入力してページアクセスした際に、404となってしまう原因を考えます。
※ 現象と解決方法から「多分こういう原因で起きてるんだろうなぁ」という考察レベルまでしか深堀しないので、もしかしたら間違ってる可能性あるので注意してください!
前提:アプリが正しく動作するためにはindex.htmlを経由する必要がある
Vue.jsでvue-routerを導入してSPAを実装した場合、ユーザがアプリにアクセスした際、サーバはデプロイされているindex.htmlにリクエストをかけることで正しくvue-routerが働いてくれてページを表示できます。
現象:ページリロードやURL入力で直接ページにアクセスしたときの動き
例えばログイン画面(https://app.com/login)に直接アクセスしようとした場合、ユーザからのアクセスを受けたサーバはindex.htmlを経由せずlogin.htmlへリクエストを掛けようとします。
ただし、アプリはSPAで実装しているためデプロイをしている実体ファイルはindex.htmlのみ(jsとかcssとか画像ファイルなど除いて)です。
そのためリクエストを受けるlogin.htmlが存在しないので、ページリロードや直接URLを入力してアクセスするした際に404となってしまっていると考えられます。
対策:サーバからのリクエストは必ずindex.htmlを通す
その問題を解決するために、先述したサーバ設定を適用し、受け取ったリクエストに対しては必ずindex.htmlを経由するような仕組みとすることでvue-routerが正しく動作して、ページリロードをしても404にならない環境を構成することができます。