by ryou

Laravelで、JSやCSSを更新した際にちゃんと反映されるようにする

どうも自分の設定が悪いのかLaravelのそもそもの仕様なのか、CSS/JSを更新しても反映されず、毎回Shift+Rでスーパーリロードして反映させていたのですが、実用上色々問題があるので対策しました。

解決法

CSS/JSファイルの末尾に「?date=〜」とファイル更新日をつけるようにし、更新された際にブラウザが別ファイルと認識するようにする。

詳細

まず、bladeテンプレート内で使用するためのディレクティブをAppServiceProvider.php内で以下のように定義する。

# AppServiceProvider.php

    public function boot()
    {
        /***********************************************************************
        ローカルのCSS,JSファイルを読み込む際に、更新日を付与することでキャッシュを
        適応するか否か判断できるようにするディレクティブ
        ファイルパスはルート相対パスで記述すること
        [使用例]
        @loadLocalCSS(/common/css/base.css)
        @loadLocalJS(/common/js/common.js)
        **********************************************************************/
        Blade::directive('loadLocalCSS', function($filePath) {
            $path = base_path() . "/public" . $filePath;
            return "<link rel=\"stylesheet\" href=\"" . $filePath . "?date=" . "<?php echo \File::lastModified(\"" . $path . "\") ?>" . "\">";
        });
        Blade::directive('loadLocalJS', function($filePath) {
            $path = base_path() . "/public" . $filePath;
            return "<script src=\"" . $filePath . "?date=" . "<?php echo \File::lastModified(\"" . $path . "\") ?>" . "\"></script>";
        });
    }

後はbladeテンプレート内で以下のような感じで記述すればOK

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>

  @loadLocalCSS(/common/css/common.css)
</head>
<body>

  ~

  @loadLocalJS(/common/js/common.js)
</body>
</html>

こうしておけば

<link rel="stylesheet" href="/common/css/common.css?date=1492222952">

みたいな感じに末尾に更新日時が(UnixTimeで)追加されるので、ファイルを更新した際に反映されるようになる。

自分はまだ使用したこと無いが、Elixirでやる方法もある模様。
ただ、あまりフロントエンドのビルドをややこしくしたくなかったのでPHP側で対処するようにした。

参考記事

https://readouble.com/laravel/5.4/ja/blade.html
キャッシュを有効にしつつ、cssやjsファイルの変更を確実に反映させる
ファイルの最終更新日時を取得する