composer install 不会生成 dist/ 或 public/build/,因其仅管理 vendor/ 下的 php 包,对前端构建产物(如 node_modules、dist、public/build)无感知;需通过 post-install-cmd 调用 npm build 或借助 asset-packagist 实现静态资源拷贝。

composer install 为什么不会生成 dist/ 或 public/build/
因为 composer install 只管 vendor/ 下的 PHP 包,对 node_modules/、dist/、public/build/ 这类前端产出目录完全无感知。你看到 JS/CSS 没出来,不是漏配,是它压根不负责这事。
常见错误现象:
-
composer require npm-asset/bootstrap成功,但public/css/bootstrap/为空 - 项目里有
package.json和"scripts": {"build": "vite build"},但composer install后dist/目录不存在 - CI 构建失败提示
Error: Cannot find module './dist/index.js',本地却正常——环境里没装 Node.js 或没执行构建
根本原因在于:Composer 不调度 Node.js 工具链。要让它“联动”,必须显式声明行为边界。
用 post-install-cmd 触发 npm build 的实操要点
在 composer.json 的 scripts.post-install-cmd 里写命令,是让 Composer 安装后顺手跑构建最直接的方式,但容易掉坑。
正确做法(以 Vite 为例):
- 确保
package.json在项目根目录,且含"build": "vite build" - 在
composer.json中添加:"scripts": { "post-install-cmd": [ "npm ci --no-audit", "npm run build" ] } - CI 环境必须预装 Node.js(否则
npm命令直接报错) - 加
--no-audit避免 npm audit 耗时阻塞,尤其在 CI 中
注意点:
-
COMPOSER_DISABLE_FUNCTIONS环境变量或--no-scripts参数会跳过所有脚本,部署时别误开 - 如果构建产物路径是
dist/,而 Web 服务器只服务public/,得额外加一步复制:cp -r dist/* public/ -
npm ci比npm install更可靠,它严格按package-lock.json还原依赖
asset-packagist + composer-asset-plugin 的适用边界
这个组合适合“只引入静态文件、不编译”的场景,比如 jQuery、Bootstrap CSS/JS 原始文件,而不是 Vue 组件库源码。
典型配置片段:
"repositories": [
{ "type": "composer", "url": "https://asset-packagist.org" }
],
"extra": {
"asset-installer-paths": {
"public/js/jquery": ["npm-asset/jquery"],
"public/css/bootstrap": ["npm-asset/bootstrap"]
}
}
关键限制:
- 只处理已发布的压缩包(如
bootstrap-5.3.3.tgz),不运行任何构建脚本 - 无法处理
exports字段或 ESM 入口,只拷贝main/style字段指向的原始文件 -
fxp/composer-asset-plugin已停止维护,PHP 8.2+ 建议改用composer/installers+ 自定义 installer,但复杂度陡增
如果你的包含 build/ 目录且希望原样复制,得在包的 composer.json 里声明 extra.asset-installer-paths,否则插件不知道该提哪几个文件。
vendor-dir 改动对前端资源路径的影响
有人想把 vendor/ 改成 third-party/,结果发现构建脚本里写的 ../vendor/autoload.php 报错——这不是 Composer 的锅,是路径硬编码没同步更新。
影响链条很直接:
-
config.vendor-dir改了 →vendor/autoload.php变成third-party/autoload.php - 如果构建脚本(如 webpack.config.js)里 require 了
../vendor/autoload.php,就得改成../third-party/autoload.php - Laravel 的
bootstrap/autoload.php默认加载vendor/autoload.php,也得跟着改 - IDE(如 PhpStorm)的自动补全和跳转会失效,需手动刷新索引或重设 include path
更隐蔽的问题:某些前端包的 PHP 封装器(如 spatie/laravel-medialibrary)会在 runtime 读取 vendor/ 下的配置或模板,路径一变就找不到资源。
真正需要改 vendor-dir 的场景极少,绝大多数情况不如老老实实用默认路径,把构建逻辑和 PHP 逻辑彻底隔离。











