0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Xserver のサブドメイン + Laravel で public/icons/ 配下の SVG だけ 404 になる問題の原因と対処法

Last updated at Posted at 2025-08-27

問題と解決

共有ホスティング(例: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="">

試したこと(時系列)

  1. パーミッション確認
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/iconspublic/assets/icons のように アプリ側のパスを変更 する。

  1. 物理ディレクトリをリネーム(or 移動)
cd /home/USER/projects/myapp/product/public
mkdir -p assets
mv icons assets/
# 以後は public/assets/icons/...
  1. 参照を更新(Blade/Provider など)
- <img src="{{ asset('/icons/icon-logout.svg') }}" alt="">
+ <img src="{{ asset('assets/icons/icon-logout.svg') }}" alt="">

asset() は引数の先頭 / の有無に関わらず /... に展開。
重要なのは /icons を使わないこと

  1. ブラウザキャッシュ対策
    ?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 静的ファイル アセット配信 トラブルシュート

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?