😏

laravelプロジェクトでesbuild使ってjsファイルのバージョニングしたい時

2021/11/21に公開

簡単にどいうことか先に説明すると、laravel デフォルトのlaravel-mixを使わずに、esbuildswcを使ってassetsをbundleした場合にlaravel-mixのmanifest.jsonファイルが作られないので、バージョニングができなくなってしまい、アプリに新しい機能のアップデートをした時にキャッシュがクリアされるまで元のキャッシュファイルが読み込まれる事が起こります、当然laravelのmix()ヘルパーも使えません。
その対策を探したところ、ピッタリの記事を見つかったので、そのまま日本語で書き残しておきたいと思います。

参考にした記事👇
https://stagerightlabs.com/blog/asset-versioning-in-laravel

流れとしては、productionの時だけphp artisan key:generateと同じ感覚でランダムの文字列を作成して、.envファイルの中を更新します、そしてBlade::directive()関数を使って、カスタムのblade関数を作ります、最後はその関数を使ってjsファイルのurlを指定します。

assets.php設定ファイルの作成

config/assets.phpファイルを作成して👇の記述を追加します。

<?php
  return [
    'version' => env('ASSETS_VERSION', null)
  ];
?>

.envファイルにキーを追加

.envファイルにassets.phpで指定しているキーを追加

ASSETS_VERSION=

ここは一旦空文字で大丈夫です。

artisanコマンド作成

php artisan make:command AssetVerioningCommand でコマンド作成します、そしたらapp\Commands\AssetVerioningCommand.phpが生成されます。

<?php

namespace App\Console\Commands;
use App\Utilities\Str;
use Illuminate\Console\Command;
use Illuminate\Console\ConfirmableTrait;
class AssetVersioningCommand extends Command
{
    use ConfirmableTrait;  //<--👈追加
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'assets:version {--force : Force the operation to run when in production}'; //<--👈変更する
    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate an asset version identifier'; //<--👈コマンドの説明
    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $key = $this->generateRandomKey();
        if (! $this->setKeyInEnvironmentFile($key)) {
            return;
        }
        $this->info('Asset version key set successfully.');
    }
    
    
    protected function generateRandomKey(): string
    {
        return Str::random(16);
    }

    /**
     * @param string $key
     */
    protected function setKeyInEnvironmentFile($key)
    {
        $currentKey = $this->laravel['config']['assets.version'];

        if (strlen($currentKey) !== 0 && (!$this->confirmToProceed())) {
            return false;
        }

        $this->writeNewEnvironmentFileWith($key);

        return true;
    }


    protected function writeNewEnvironmentFileWith($key)
    {
        file_put_contents($this->laravel->environmentFilePath(), preg_replace(
            $this->keyReplacementPattern(),
            'ASSETS_VERSION=' . $key,
            file_get_contents($this->laravel->environmentFilePath())
        ));
    }

    protected function keyReplacementPattern()
    {
        $escaped = preg_quote('=' . $this->laravel['config']['assets.version'], '/');

        return "/^ASSETS_VERSION{$escaped}/m";
    }
}

AppServiceProvider.phpに記述追加

次はAppServiceProvider.phpboot()関数にカスタムBlade関数を登録します。

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('version', function ($path) {
            return "<?php echo config('assets.version') ? asset({$path}) . '?v=' . config('assets.version') : asset({$path}); ?>";
        });
    }
}

blade.phpの記述を変更


<!-- <script src="{{ mix('js/public/app.js') }}" defer></script> -->
<!-- 👇に変更 -->
<script src="@version('js/public/app.js')" defer></script>

laravelを再起動すれば、反映されるはずです。🤗

Discussion