問題と解決
共有ホスティング(例:Xserver)では /icons/
がサーバ側の予約エイリアス になっていることがあり、アプリの public/icons/...
へ届く前にサーバ設定に“奪われ”ます。
ディレクトリ名を /assets/icons
などに変更(または Vite に載せる)だけで解決。
環境
- 共有ホスティング:Xserver(フロント Nginx/裏で Apache・PHP-FPM)
- デプロイ:サブドメインのドキュメントルート → Laravel の
public
へシンボリックリンク- 例:
/home/USER/public_html/sub.example.com
→/home/USER/projects/myapp/product/public
- 例:
- PHP:8.2(CLI)
- Laravel:v12
- Basic 認証:サブドメイン配下のみ
.htaccess
で適用
症状
public/icons/
にファイルはあるのに、URL で叩くと 404 Not Found。
# サーバ上で存在確認
ls -l /home/USER/projects/myapp/product/public/icons/icon-logout.svg
# => -rw-r--r-- 1 USER USER 272 ... public/icons/icon-logout.svg
# でも URL は 404
curl -I https://sub.example.com/icons/icon-logout.svg
# => HTTP/1.1 404 Not Found
Blade 側の参照例:
<img src="{{ asset('/icons/icon-logout.svg') }}" alt="">
試したこと(時系列)
- パーミッション確認
stat public/icons
stat public/icons/icon-logout.svg
→ 755
/ 644
で問題なし。
仮配信テスト(別パスで同じファイルを配信)
cd /home/USER/projects/myapp/product/public
mkdir -p site-icons
cp -a icons/* site-icons/
curl -I https://sub.example.com/site-icons/icon-logout.svg
# => HTTP/1.1 200 OK ← これは通る
→ /icons
のパスだけが 404 と確定。
原因
共有ホスティングのサーバ側設定(Apache のグローバル設定など)で /icons/
が予約パス(エイリアス) になっており、アプリ側に届く前に Web サーバが処理してしまう。
この サーバ側の Alias が優先 されるため、アプリの public/icons
に同名ディレクトリを置いても .htaccess
では基本的に上書きできない。
例:Apache 既定の
Alias /icons/ "/usr/share/apache/icons/"
のような設定。
共有環境ではこの層をユーザーが変更できないため、/icons
は安全でないパス名。
解決策 1:ディレクトリ名を変える
public/icons
→ public/assets/icons
のように アプリ側のパスを変更 する。
- 物理ディレクトリをリネーム(or 移動)
cd /home/USER/projects/myapp/product/public
mkdir -p assets
mv icons assets/
# 以後は public/assets/icons/...
- 参照を更新(Blade/Provider など)
- <img src="{{ asset('/icons/icon-logout.svg') }}" alt="">
+ <img src="{{ asset('assets/icons/icon-logout.svg') }}" alt="">
asset()
は引数の先頭/
の有無に関わらず/...
に展開。
重要なのは/icons
を使わないこと。
- ブラウザキャッシュ対策
?v=1
などのクエリを一時付与、または DevTools でキャッシュ無効化。
解決策 2:Vite に載せる(ビルド管理)※投稿主未実施
resources/
下へ置いて Vite で配信(/build/...
になり /icons
を回避)。
- 例:
resources/images/icons/icon-logout.svg
- Blade:
@vite(['resources/js/app.js']) {{-- 既に読み込んでいれば不要 --}}
<img src="{{ Vite::asset('resources/images/icons/icon-logout.svg') }}" alt="">
- あるいは CSS / JS から import して参照。
避けたい回避策
-
.htaccess
で/icons
をリライト上書き → 共有環境ではサーバの Alias が勝つ ため期待通り動かないことが多い -
/icons
をシンボリックリンクで張り直す → 同様に効果薄
結果
-
/icons
をやめて/assets/icons
に変更後、即 200 が返るようになり、全画面でアイコンが表示されました。
Tags
Laravel
Xserver
Nginx
Apache
Vite
静的ファイル
アセット配信
トラブルシュート