Laravel
× Vite
× jQuery
のプロジェクトでビルド・デプロイした際に色々うまくいかないことがあったので、自分のための備忘録として記載します。
前提
使用バージョン
以下のバージョンを使用しています。
PHP 8.3
Laravel 10.48
Vite v5.2
Node v20.12
ビルド・デプロイ時に遭遇したエラー
① 静的アセットの設定をしておかないとビルド時に画像が読み込まれない
<img>
から呼び出す画像があったため、以下の記事を参考にして対応しました。
今回はプロジェクトのresources/img
ディレクトリに画像ファイルを配置していたので、以下のように追記しました。
+ import.meta.glob([
+ '../img/**',
+ ]);
② jQueryが読み込まれない
Uncaught ReferenceError: jQuery is not defined
ビルド後に上記のエラーが出ており、jQuery
が読み込まれていないんだなと察します。その時のapp.js
は以下でした。
import './bootstrap';
import './jquery-3.7.1.min';
調べると、jQueryをインストールする必要があるようです。npm install jquery
します。
npm install jquery
以下を参考にして、設定等を変更します。
import './bootstrap';
- import './jquery-3.7.1.min';
+ import $ from 'jquery';
+ window.jQuery = window.$ = $
export default defineConfig({
+ build: {
+ rollupOptions: {
+ output: {
+ globals: {
+ jquery: 'window.jQuery',
+ }
+ }
+ }
+ },
});
これでjQueryも無事に動くようになりました
どうしてViteでjQueryを読み込めなかった?
Viteで以下の様に読み込んでいるのに、ビルドした時にjQueryを読み込まなかった理由が気になりました。
import './jquery-3.7.1.min';
良い調べ方が思い浮かばなかったので、生成AIのphindさんに聞いてみました。
Integrating jQuery with Vite can be challenging due to differences in module systems and how Vite optimizes dependencies. Vite uses ES modules, whereas jQuery is traditionally used as a global variable attached to the window object. This discrepancy can lead to issues like $ is not defined errors when trying to use jQuery in a Vite project.
回答を意訳とすると、
- モジュールシステムの違いと、Viteが依存関係を最適化する方法により、ViteとjQueryの統合は難しい
- Vite : ESモジュール
- jQuery : グローバル変数としてwindowオブジェクトにアタッチされて使用される
モジュールシステムの違いが大きいのだろうか...
※ もう少し詳しく調べて追記したいと思います
③ http
でアクセスしようとしてChromeにブロックされる
CSSが反映されていない!とコンソールを確認したところ「HTTPS
経由で読み込まれたページが、HTTP
経由でスタイルシートをリクエストしようとしてたからブロックした」旨のメッセージが...
Mixed Content: The page at 'https://xxxx.jp' was loaded over HTTPS, but requested an insecure stylesheet 'http://xxxx.jp/build/assets/app-xxx.css'. This request has been blocked; the content must be served over HTTPS.
ひとまずAppServiceProvider.php
にURL::forceScheme('https');
を追加することで解消しました。
// boot() に追加
+ if (! app()->isLocal() && ! app()->runningUnitTests()) {
+ URL::forceScheme('https');
+ }
上記解決策は、URLスキーマを強制的にhttps
にしているものです (Vite
で何らかの設定を行えば、Laravel
でわざわざスキーマを強制しなくてもいけそうではあるんですがやり方が分からず...)。
Apacheの設定
唐突ですが、今回のシステムにおけるApacheの設定の話をします。
今回はApache
のドキュメントルート/var/www/html
以下に
- APIの
api
ディレクトリ - 管理画面の
admin
ディレクトリ - 利用者向け画面
user
ディレクトリ
があり、各ディレクトリごとにLaravel
プロジェクトがあります。
/var
└─ www
└─ html
├─ api // APIのLaravelプロジェクト
├─ admin // 管理画面のLaravelプロジェクト
└─ user // 利用者向け画面のLaravelプロジェクト
パス/api
にリクエストが来た場合は/var/www/html/api
で処理を行う...というのでApache
のvhost.conf
は以下の設定になっています。
<VirtualHost *:80 *:443>
ServerName xxxx.jp
DocumentRoot /var/www/html
<Directory "/var/www/html">
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
RewriteEngine On
# /api へのアクセスは /var/www/html/api/public へ
RewriteCond %{REQUEST_URI} !^/api/public
RewriteRule ^/api(/.*)?$ /api/public$1 [L]
# /admin へのアクセスは /var/www/html/admin/public へ
RewriteCond %{REQUEST_URI} !^/admin/public
RewriteRule ^/admin(/.*)?$ /admin/public$1 [L]
# /user へのアクセスは /var/www/html/user/public へ
RewriteCond %{REQUEST_URI} !^/user/public
RewriteRule ^/user(/.*)?$ /user/public$1 [L]
DirectoryIndex public/index.php
</VirtualHost>
この設定の影響を受けたと見られるエラーが以降に続きます。
④ ASSET_URL
にパスを指定しなかったのでjsファイルなどが404になる
続いては、Laravelの.env
ファイルの環境変数の話です。
コンソールでjsファイルなどが軒並み404エラーになって慌てました。
どうやらbuild/assets/app.js
を見に行って404になっていたようです。
先述したように、https://xxxx.jp/user
パスにアクセスされた場合、/var/www/html/user/public
で処理を行うようにしています。
Apacheさんにはuser/build/assets/app.js
を取得して欲しいので、ASSET_URL
にパスを追加します。
- ASSET_URL="${APP_URL}"
+ ASSET_URL="${APP_URL}/user"
⑤ base
にパスを指定しなかったのでCSS内にある画像ファイルが404になる
やっとCSSが読み込まれた!わーい!と喜んでいたのもつかの間。
コンソールを見ると、CSS内で使用している画像が読み込まれていない...
エラー内容的に、再びパスの/user
が欠けているがゆえのエラーだったので、vite.config.js
に以下を追記します。
+ base: '/user/build/',
この設定を追加して、デプロイ時にCSSの画像などが参照されて一安心、としていたら、
今度はローカル環境で開発中(npm run dev
を実行)にCSSが反映されないときた...。まあbuild
ってパスに入っているし...。
そのため、base
を「ローカル環境なら/user/
、それ以外の環境なら/user/build/
」と設定することで凌ぐことにしました。
このあたり、かなり手探りなので、もっといいやり方があるよというのがあればご教授お願いします
npm run dev
を動かしている時、現在の環境をローカル環境としたいと思います。
じゃあViteのimport.meta.env.DEV
を使ってこうだ!
base: import.meta.env.DEV ? '/user/' : '/user/build/',
TypeError: Cannot read properties of undefined (reading 'DEV')
ダメだった...
import.meta.env.ENV
はvite.config.js
では使えなさそうなのでprocess.env.NODE_ENV
で判定するようにします。
npm run dev
の起動時に、NODE_ENV = local
となるように設定しました。
"scripts": {
- "dev": "vite",
+ "dev": "NODE_ENV=local vite",
}
- base: '/user/build/',
+ process.env.NODE_ENV === 'local' ? '/user/' : '/user/build/',
ひとまずこれでローカル環境での開発時にもCSSが読み込まれるようになりました。
余談 : npm run dev
と .env
ファイル
ローカル環境でnpm run dev
としてViteを起動すると、LaravelのAPP_URL
を.env.development
から読み込んでしまい困りました
VITE v5.1.6 ready in 199 ms
➜ Local: http://localhost:5173/user/
➜ Network: http://XXX.XX.X.X:5173/user/
➜ press h + enter to show help
LARAVEL v10.48.4 plugin v1.0.2
➜ APP_URL: https://開発環境FQDN #.env.developのAPP_URL
違う、そうじゃない。.env
か.env.local
のAPP_URL
を読み込んでおくれ...。
.env
ファイルの設定
.env
ファイルは4種類用意し、環境によってコピー元を変えるようにして運用しています。
-
.env.local
:ローカル環境用ファイル -
.env.testing
:ローカル環境テスト用ファイル -
.env.development
:開発環境用ファイル -
.env.production
:本番環境用ファイル
# .env.local
APP_ENV=local
APP_URL=http://localhost:8080
# .env.testing
APP_ENV=testing
APP_URL=http://localhost
# .env.development
APP_ENV=development
APP_URL=https://開発環境FQDN
# .env.production
APP_ENV=production
APP_URL=https://本番環境FQDN
Viteのモードと.env
ファイル
Viteの仕様として「モード」の仕組みがあり、dev
コマンドはdevelopment
モードで動作します。
特定のモードの env ファイル(例: .env.production
)は、汎用の env ファイル(例: .env
)よりも優先されます。1
今回で言えば、.env.development > .env
の優先順位になっているようです。
では、モードにlocal
を指定すれば良いのでは?
"scripts": {
- "dev": "vite",
+ "dev": "vite --mode local",
},
npm run dev
> dev
> vite --mode local
error when starting dev server:
Error: "local" cannot be used as a mode name because it conflicts with the .local postfix for .env files.
モードにlocal
は指定できなかった...ぐぬぬ...
プロジェクトでは
-
.env.local
: ローカル環境の環境変数 -
.env.development
: 開発環境の環境変数
をセットしていました。
しかしnpm run dev
を叩く時はローカル環境なので、.env.development
ではなく、.env
OR .env.local
を読み込んで欲しいです。
なので今回は、npm run dev
を実行時に、.env
のファイルを読み込んでもらうようにしました。Node v20.12.0以降で使えるprocess.loadEnvFile()
を使用します。
export default defineConfig({
+ define: {
+ // .envを読み込む
+ 'process.env': process.loadEnvFile('.env')
+ },
});
npm run dev
を実行した際に、LARAVELのAPP_URLがローカル環境用の値になりました。
VITE v5.1.6 ready in 199 ms
➜ Local: http://localhost:5173/user/
➜ Network: http://XXX.XX.X.X:5173/user/
➜ press h + enter to show help
LARAVEL v10.48.4 plugin v1.0.2
➜ APP_URL: http://localhost:8080 # .env.localをコピーして作られた.envのAPP_URL
とりあえず今回は上記で対応したのですが、どうやるのが一番良かったのだろうな、と考える日々です。