
composer.json 的 archive 配置能排除哪些文件
Composer 本身不提供“下载时跳过某些文件”的运行时开关,但支持在包发布阶段通过 archive 字段声明哪些路径不被打包进 dist(即 zip/tar.gz 分发包)。这意味着:你无法让 composer install 主动忽略已下载的文件,但可以控制别人发布的包里不包含 .git、tests/、docs/ 这类非运行必需内容。
常见误操作是试图在自己项目根目录的 composer.json 里加 archive——这没用,它只对 packagist 上以 package 形式发布的库生效,且必须写在该库自己的 composer.json 中。
-
archive是 package 维护者配置的,不是使用者配置的 - 生效前提是 packagist 使用 dist 方式安装(默认开启),且源包已按此配置重新打包发布
- 支持通配符:
"exclude": [".git", "/tests/*", "docs/**"]
想跳过 vendor 里某个包的特定文件?用 installer-paths 不行,得靠 scripts + post-install-cmd
如果你的目标是“装完某包后立刻删掉它的 src/Tests 或 example/ 目录”,composer.json 没有内置过滤机制,但可以用脚本补救。关键是把清理逻辑绑定到 post-install-cmd 或 post-update-cmd。
例如,删除 monolog/monolog 包里的测试文件:
"scripts": {
"post-install-cmd": [
"rm -rf vendor/monolog/monolog/tests",
"rm -rf vendor/monolog/monolog/examples"
],
"post-update-cmd": [
"rm -rf vendor/monolog/monolog/tests",
"rm -rf vendor/monolog/monolog/examples"
]
}
- Windows 用户需改用
del /s /q或 PowerShell 命令,或统一用 PHP 脚本避免平台差异 - 命令执行顺序无保证,多个包清理建议合并为一个 PHP 脚本调用,更可控
- 注意权限问题:某些系统下
vendor/可能被设为只读,rm -rf失败时 Composer 不会中止安装
composer install --no-dev 和 autoload-dev 的真实作用边界
很多人以为 --no-dev 能跳过所有开发相关文件,其实它只影响两件事:不安装 require-dev 下的包,不加载 autoload-dev 配置里的 PSR-4/ClassMap。它完全不删源码里的 tests/ 或 examples/ 目录。
-
autoload-dev仅控制自动加载行为,和文件是否存在无关 - 即使设置了
"autoload-dev": {"psr-4": {"Monolog\Tests\": "tests/"}},--no-dev也不会删掉tests/文件夹 - 真正减少磁盘占用,还得靠前面提到的
archive(上游控制)或脚本(下游清理)
为什么不用 .gitattributes 或 export-ignore
GitHub/GitLab 仓库若启用 dist 安装(即从 zip 下载),Composer 默认会调用 git archive,此时 .gitattributes 中的 export-ignore 生效。但这只适用于你 own 的包,并且要求 packagist 同步时走的是 Git export 流程(而非 GitHub API 直接拉 zip)。
实际中风险高:很多私有包托管在 GitLab 自建实例,export-ignore 不被识别;而 Packagist.org 对 GitHub 仓库已切换为 API 下载,绕过 git archive,导致 .gitattributes 彻底失效。
- 别依赖
.gitattributes控制 Composer 分发内容,兼容性差 - 优先使用
archive.exclude,它是 Composer 官方支持的、明确的分发过滤方式 - 如果必须用 Git 属性,记得验证 packagist 同步日志里是否出现
Using git archive
archive.exclude 只在 packagist 重新抓取并构建 dist 包后才生效,改了配置不触发重打包,旧 zip 依然含被排除的文件**。维护私有包时,务必手动触发更新或等下一版 tag 发布。










