はじめに
「Laravelの画面が真っ白になって何も表示されない」という事象は定期的に話題になるようです。自分でも過去に2~3回あったような気がしますが、原因が多種多様なので、なかなかまとまった記事にならないようです。今回もこのようなケースの一つとしてご紹介します。
なお言い訳になりますが、Laravel + Vue 周りの構築と開発は他の方が行っており、筆者も正しく理解できているわけではありません。あくまでも「こういうことではないか」という推測に過ぎないのでご理解願います。再現性はあるので、おそらく間違いないとは思いますが。
バージョン(主たる関係者)
- httpd 2.4.37
- Laravel 9.21.5
- Vue 2.6.14
- laravel-vite ^0.0.19
- Grafana 9.1.5
開発環境
現在流行している Sail + Docker 環境は(開発要員も含む)環境的な制約により実現できておらず、若干名が Vagrant 環境、その他は社内に建てた共有サーバ上の環境を使っています。以下は主に Vagrant を前提とした話になります。
事象
- 画面が真っ白
- storage/logs/ には特に記載なし(=Laravelとしては正常終了)
- ブラウザでページのソースを見ると、html の骨格だけはきちんと届いている(HTTP 200 OK)。
調査
開発者ツールで見ると、以下のエラーが起こっています。
しくみを完全に理解できているわけではないですが、どうも html の大枠を持ってきた後、個別に client と app.js というのを取りに行こうとして Connection Refused になっているようです。肝心のコンテンツ部分がないので、ブラウザの画面としては真っ白となります。
ワークアラウンド
これでは仕事にならないので、何かできることはないかといろいろ試した結果、APP_ENV を production にしたら表示されることがわかりました。
$ grep APP_ENV .env
APP_ENV=production
社内サーバについてはこれで大丈夫になりました。ただしこの状態だと、VSCode(つまり Xdebug)でトレースができないことがわかりました。これは開発者としてはかなりツラいです。
原因
APP_ENV=local だとトレースできるので、なんとかこの環境で動かせないかとさんざん悩んだ結果、ようやく原因にたどりつけました。
どうも APP_ENV=local の場合、コンテンツの配信を行う部分が、httpd に加えて Vite のサーバ機能を併用するようです。で、我々の環境では Vite はポート 3000 を使っている、ということのようです。
$ grep 3000 vite.config.js
}).merge({ server: { host: true, port: 3000 } })
で、運の悪いことに、今回のシステムは Grafana と連動しているのですが、Grafana のデフォルトポートが 3000 なのです。grafana-server はシステム起動時に自動起動するのでこちらが優先となり、Vite は 3000 を Listen できない状態になっていたようです。
# httpd の設定
$ cat /etc/httpd/conf.d/1_grafana.conf
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /grafana http://127.0.0.1:3000
ProxyPassReverse /grafana http://127.0.0.1:3000
# grafana の設定
$ sudo grep 3000 /etc/grafana/grafana.ini
; http_port = 3000
今回は、grafana 側の上記の設定を 3001 にすることで、前述の現象は解消され、めでたく XDebug でトレースできるようになりました。
なお、APP_ENV=production の場合、localhost:3000 の代わりに本来の httpd に対してアクセスするようになり、上記の事象は起きない、ということのようです。
素朴な疑問
現在の環境は、ブラウザが母艦(Windows)、httpd + Laravel が仮想マシン上(Host Only Network 経由)です。で、ブラウザから見ると、127.0.0.1:3000 は Windows 上の話のような気がするので、なぜ仮想マシン側でポート番号をずらしたら解消するのかが、今ひとつスッキリしません。
$ sudo ss -tlnp | grep grafana
LISTEN 0 128 *:3000 *:* users:(("grafana-server",pid=9092,fd=16))
Vue + Vite 勉強しないと…。