public 中的文件也不会自动改变。为了避免只有 PHP 代码变成新版本、而浏览器仍在使用旧版本资源的情况,需要确定发布目标的所有者以及更新步骤。
本页以Laravel 包开发为前提,从 Laravel 13 的发布处理出发,梳理分发与维护的设计。实现的确认基于 laravel/framework 的 v13.35.0。
发布既不是构建也不是同步
ServiceProvider::publishes() 用于注册复制源和复制目标。实际复制文件的是 vendor:publish。它不会进行 JavaScript 转译、CSS 构建,也不会添加到应用程序的 Vite 入口中。
如果由包分发已构建好的文件,可以采用如下结构。
public/vendor/courier/courier.css 和 courier.js。如果设计为以普通 CSS 和 JavaScript 的形式分发,可以在 Blade 中按如下方式引用。
asset() 是生成 URL 的辅助函数,它不负责构建、发布,也不会根据内容生成文件名。
标签不是 Provider 专属的命名空间
ServiceProvider 会把发布路径分别注册到按 Provider 类划分的数组和按标签划分的数组中。按标签划分的数组由多个 Provider 共享,因此如果使用 public 这样的通用标签,其他包也可能成为对象。
同时指定两者时,
pathsForProviderAndGroup() 会以复制源路径为键使用 array_intersect_key()。这并不是根据标签切换到不同复制目标的机制。请避免多次注册同一个复制源、为其设置不同用途的复制目标的设计。
--tag 可以重复指定,此时会依次发布各个标签。--all 会在选择处理的开头直接返回,因此即使同时加上 --provider 或 --tag,也不会用于缩小范围。
区分使用重新发布选项
VendorPublishCommand 的文件发布和目录发布会根据复制目标文件是否存在以及选项来判断是否复制。下表是针对复制源中存在的普通资源文件的行为。
--existing 并不是保护编辑内容的选项。它会覆盖已有文件,但不会发布新版本中新增的文件。如果更新后的 JavaScript 需要新增的文件,仅使用 --existing 可能无法让构建产物齐全。
如果约定由包管理发布目标、用户不直接编辑,则在更新后执行以下命令。
已删除的文件会残留在发布目标中
目录发布的moveManagedFiles() 会遍历复制源中的文件并写入。它没有查找并删除仅存在于发布目标中的文件的处理。--force 也不会实现目录的完全同步。
例如,即使在新版本中删除了 legacy.js,如果已经发布过旧版本,public/vendor/courier/legacy.js 仍会残留。重命名时旧名称的文件同样会残留,因此请在发布说明中记录已删除、已重命名的文件以及引用位置的变更。
如果提供清除旧文件的步骤,请具体指明包所拥有的文件。不要设计成整体删除可能放有用户自有文件的目录的步骤。
加入 laravel-assets 意味着接受覆盖约定
Laravel 13 的官方应用程序骨架在composer.json 的 post-update-cmd 中包含如下脚本。
publishes() 的第 2 个参数改为数组,将同一资源注册到两个标签中。
laravel-assets 并不是带有特殊复制处理的标签。由于骨架中的脚本会以带 --force 的方式发布该标签,加入其中的文件会在 Composer 更新时成为覆盖对象。请不要注册用户会编辑的配置或视图。
自动更新的前提是:应用程序一侧存在该脚本、该事件会被执行,并且 Provider 已注册发布路径。为了在不满足这些前提的部署中也能完成更新,请提供使用包专属标签的重新发布命令。
在部署中保持 PHP 与资源的版本一致
config:cache 和 view:cache 不会改写已发布的 JavaScript 和 CSS。如果设计为发布后仍以相同 URL 提供,浏览器或 CDN 的缓存可能导致使用旧内容。请把反映分发物版本的 URL、缓存失效等应用程序的分发策略也纳入更新步骤。
每次发布版本时,请确认以下组合。
- 在尚未发布的应用程序中,所有必要的构建产物都会被发布。
- 在已发布旧版本的状态下,
--force会更新已有文件并添加新文件。 - 资源更新不会覆盖用户的配置、视图和自有 CSS。
- 已明确说明已删除、已重命名文件的处理方式,且不再残留对旧版本的引用。
- 通过实际的分发 URL 能获取到新版本的内容,PHP 与浏览器端的处理能够协同工作。
相关页面
包自动发现
确认 Composer 更新、Provider 发现与文件发布之间的区别。
包视图的覆盖与更新
确认用户自定义模板的维护方针。
包缓存与 optimize 的集成
讲解与文件发布分开管理的包缓存。
版本兼容性管理
将发布目标和分发格式的变更作为兼容性约定来处理。
参考的一手资料
- Laravel 官方文档:Public assets
- Laravel 官方文档:Publishing file groups
- Laravel Framework v13.35.0:ServiceProvider —
publishes()、addPublishGroup()、pathsToPublish()、pathsForProviderAndGroup()。 - Laravel Framework v13.35.0:VendorPublishCommand — 选择范围、覆盖条件、目录内的复制处理。
- Laravel 13 官方应用程序骨架:composer.json — 通过
post-update-cmd重新发布laravel-assets。