> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# パッケージの公開アセットと更新

> Laravel 13の公開処理を読み解き、JavaScript・CSSの配布、タグの選択範囲、上書きオプション、Composer更新時の再公開を長期保守の観点で解説します。

パッケージのJavaScriptやCSSを更新しても、アプリケーションの `public` にコピー済みのファイルは自動では変わりません。PHPコードだけが新版になり、ブラウザーが旧版のアセットを使い続ける状態を防ぐには、公開先の所有者と更新手順を決める必要があります。

このページでは[パッケージ開発の基礎](/jp/advanced/package-development)を前提に、Laravel 13の公開処理から配布と保守の設計を整理します。実装の確認には `laravel/framework` の `v13.35.0` を使用しています。

## 公開はビルドでも同期でもない

`ServiceProvider::publishes()` はコピー元とコピー先を登録します。実際にファイルをコピーするのは `vendor:publish` です。JavaScriptのトランスパイルやCSSのビルド、アプリケーションのViteエントリへの追加は行いません。

パッケージ側でビルド済みのファイルを配布する場合、たとえば次の構成にします。

```text theme={null}
courier/
├── public/
│   ├── courier.css
│   └── courier.js
└── src/
    └── CourierServiceProvider.php
```

```php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        if ($this->app->runningInConsole()) {
            $this->publishes([
                __DIR__.'/../public' => public_path('vendor/courier'),
            ], 'courier-assets');
        }
    }
}
```

初回の公開では、プロバイダーとタグを明示します。

```bash theme={null}
php artisan vendor:publish --provider="Acme\Courier\CourierServiceProvider" --tag=courier-assets
```

この例では `public/vendor/courier/courier.css` と `courier.js` が作られます。通常のCSSとJavaScriptとして配布する設計なら、Bladeから次のように参照できます。

```blade theme={null}
<link rel="stylesheet" href="{{ asset('vendor/courier/courier.css') }}">
<script src="{{ asset('vendor/courier/courier.js') }}" defer></script>
```

ES modulesとして配布する場合などは、配布形式に合わせて読み込み方を変更します。`asset()` はURLを生成するヘルパーであり、ビルドや公開、内容に応じたファイル名の生成をするものではありません。

<Warning>
  コピー元には、公開してよいビルド成果物だけを置いてください。この例の公開先はWebからアクセスできる `public` です。設定ファイルや内部データを同じ公開グループに含めないでください。
</Warning>

## タグはプロバイダー専用の名前空間ではない

`ServiceProvider` は公開パスをプロバイダークラス別の配列と、タグ別の配列に登録します。タグ別の配列は複数のプロバイダーで共有されるため、`public` のような汎用タグを使うと他のパッケージも対象になり得ます。

| 指定 | 選ばれる公開パス |
| - | - |
| `--tag=courier-assets` | そのタグを登録したすべてのプロバイダーのパス |
| `--provider="Acme\Courier\CourierServiceProvider"` | そのプロバイダーが登録したすべてのパス |
| プロバイダーとタグの両方 | そのプロバイダーのパスと、そのタグのパスの共通部分 |
| `--all` | すべてのプロバイダーの公開パス |

両方を指定したとき、`pathsForProviderAndGroup()` は**コピー元パスをキーとして** `array_intersect_key()` を使います。タグによって別のコピー先へ切り替える仕組みではありません。同じコピー元を何度も登録して用途別のコピー先を持たせる設計は避けてください。

`--tag` は繰り返し指定できます。その場合は各タグを順に公開します。`--all` は選択処理の冒頭で戻るため、`--provider` や `--tag` を同時に付けても絞り込みには使われません。

<Tip>
  利用者の設定やビューまで上書きしないよう、更新手順ではパッケージ固有のアセットタグを使います。プロバイダーだけを指定して `--force` を付けると、同じプロバイダーの設定やビューも対象になり得ます。
</Tip>

## 再公開オプションを使い分ける

`VendorPublishCommand` のファイル公開とディレクトリ公開は、コピー先ファイルの存在とオプションを使ってコピーを判断します。次の表は、コピー元に存在する通常のアセットファイルについての動作です。

| オプション | コピー先に存在しないファイル | コピー先に存在するファイル |
| - | - | - |
| なし | 追加する | 保持する |
| `--force` | 追加する | 上書きする |
| `--existing` | 追加しない | 上書きする |
| `--existing --force` | 追加しない | 上書きする |

`--existing` は編集を保護するオプションではありません。既存ファイルを上書きする一方、新版で追加されたファイルは公開しません。JavaScriptが新しい追加ファイルを必要とする更新では、`--existing` だけでは成果物がそろわない可能性があります。

パッケージが公開先を管理し、利用者が直接編集しない契約なら、更新後に次を実行します。

```bash theme={null}
php artisan vendor:publish --provider="Acme\Courier\CourierServiceProvider" --tag=courier-assets --force
```

<Warning>
  `--force` は差分をマージせず、利用者の編集も上書きします。利用者がカスタマイズするCSSは別ファイルとして読み込むなど、パッケージ管理の成果物と分離してください。設定やビューのカスタマイズとは更新方針を分けます。
</Warning>

### 削除したファイルは公開先に残る

ディレクトリ公開の `moveManagedFiles()` は、コピー元にあるファイルを走査して書き込みます。公開先にしかないファイルを探して削除する処理はありません。`--force` もディレクトリの完全同期にはなりません。

たとえば新版で `legacy.js` を削除しても、旧版を公開済みなら `public/vendor/courier/legacy.js` は残ります。改名した場合も旧名のファイルは残るため、リリースノートには削除・改名したファイルと参照先の変更を記録します。

旧ファイルを除去する手順を提供する場合は、パッケージが所有するファイルを具体的に示してください。利用者の独自ファイルが置かれている可能性のあるディレクトリを丸ごと削除する手順にはしません。

## laravel-assetsへの参加は上書き契約を意味する

Laravel 13の公式アプリケーション雛形には、`composer.json` の `post-update-cmd` に次のスクリプトがあります。

```json theme={null}
{
    "scripts": {
        "post-update-cmd": [
            "@php artisan vendor:publish --tag=laravel-assets --ansi --force"
        ]
    }
}
```

これはアプリケーション側のスクリプトです。パッケージの自動検出そのものが公開ファイルを更新しているわけではありません。既存アプリケーションではスクリプトが変更・削除されている場合もあるため、利用側の設定を確認します。

この更新経路へ参加する場合は、先ほどの `publishes()` の第2引数を配列に変更して、同じアセットを2つのタグへ登録します。

```php theme={null}
$this->publishes([
    __DIR__.'/../public' => public_path('vendor/courier'),
], ['courier-assets', 'laravel-assets']);
```

`laravel-assets` は特別なコピー処理を持つタグではありません。雛形のスクリプトがそのタグを `--force` 付きで公開するため、参加したファイルはComposer更新時の上書き対象になります。利用者が編集する設定やビューは登録しないでください。

<Info>
  自動更新の前提は、アプリケーション側にスクリプトがあり、そのイベントが実行され、プロバイダーが公開パスを登録していることです。この前提を満たさないデプロイでも更新できるよう、パッケージ固有のタグを使った再公開コマンドを案内します。
</Info>

## デプロイでPHPとアセットの版をそろえる

```mermaid theme={null}
flowchart TD
    A["パッケージを更新"] --> B["公開パスを登録"]
    B --> C["固有タグでvendor:publish --force<br>またはlaravel-assetsの更新スクリプト"]
    C --> D["新しいファイルを追加<br>既存ファイルを上書き"]
    D --> E["指定された旧ファイルの整理<br>ブラウザー・CDNのキャッシュ方針を適用"]
    E --> F["PHPとアセットが同じ版で動くことを確認"]
```

`config:cache` や `view:cache` は公開済みのJavaScript・CSSを書き換えません。公開後も同じURLで配信する設計なら、ブラウザーやCDNのキャッシュによって古い内容が使われることがあります。配布物のバージョンを反映したURLやキャッシュ無効化など、アプリケーションの配信方針も更新手順に含めます。

リリースごとに次の組み合わせを確認します。

* 未公開のアプリケーションで、必要なビルド済みファイルがすべて公開される。
* 旧版を公開済みの状態で、`--force` によって既存ファイルが更新され、新しいファイルが追加される。
* アセット更新が利用者の設定・ビュー・独自CSSを上書きしない。
* 削除・改名したファイルの扱いが明示され、旧版の参照が残っていない。
* 実際の配信URLで新版の内容が届き、PHPとブラウザー側の処理が連携する。

## 関連ページ

<Columns cols={2}>
  <Card title="パッケージ自動検出" icon="magnifying-glass" href="/jp/advanced/package-discovery">
    Composerの更新、プロバイダーの検出、ファイル公開の違いを確認します。
  </Card>

  <Card title="パッケージビューの上書きと更新" icon="eye" href="/jp/advanced/package-views">
    利用者がカスタマイズするテンプレートの保守方針を確認します。
  </Card>

  <Card title="パッケージのキャッシュとoptimizeへの統合" icon="gears" href="/jp/advanced/package-optimization">
    ファイル公開とは別に管理するパッケージキャッシュを解説します。
  </Card>

  <Card title="バージョン互換性管理" icon="code-branch" href="/jp/advanced/package-versioning">
    公開先や配布形式の変更を互換性の契約として扱います。
  </Card>
</Columns>

## 参照した一次情報

* [Laravel公式ドキュメント: Public assets](https://github.com/laravel/docs/blob/13.x/packages.md#public-assets)
* [Laravel公式ドキュメント: Publishing file groups](https://github.com/laravel/docs/blob/13.x/packages.md#publishing-file-groups)
* [Laravel Framework v13.35.0: ServiceProvider](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Support/ServiceProvider.php) — `publishes()`、`addPublishGroup()`、`pathsToPublish()`、`pathsForProviderAndGroup()`。
* [Laravel Framework v13.35.0: VendorPublishCommand](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Foundation/Console/VendorPublishCommand.php) — 選択範囲、上書き条件、ディレクトリ内のコピー処理。
* [Laravel 13公式アプリケーション雛形: composer.json](https://github.com/laravel/laravel/blob/13.x/composer.json) — `post-update-cmd` による `laravel-assets` の再公開。


## Related topics

- [Laravelパッケージ開発](/jp/advanced/package-development.md)
- [応用トピック](/jp/advanced/index.md)
- [パッケージのマイグレーション公開と更新](/jp/advanced/package-migrations.md)
- [パッケージビューの上書きと更新](/jp/advanced/package-views.md)
- [パッケージの静的解析（PHPStan / Larastan）](/jp/advanced/package-static-analysis.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.