镜像源不支持archive.excludes,仅原样同步Packagist已构建的dist包;排除效果取决于包作者是否用新tag触发按该配置重建ZIP,镜像本身不解析或执行该规则。

Composer镜像源是否支持archive.excludes?
不支持。镜像源(如阿里云、腾讯云、华为云等 packagist.org 镜像)只同步 packages.json 和 dist 包(ZIP/TAR),archive.excludes 是包作者在自己 composer.json 中声明的打包规则,镜像不会解析或执行它——它只原样转发 dist 包内容。
这意味着:你看到某个包在 Packagist 页面显示 “excludes: [tests/ docs/]”,但镜像源拉下来的 ZIP 文件里依然可能包含这些目录,只要原 dist 包没按该配置重建。
- 镜像源不参与
composer archive构建流程,也不读取源码仓库里的.gitattributes - dist 包一旦生成并上传到 Packagist,镜像就直接缓存该 ZIP 文件;后续即使作者更新了
archive.excludes,旧 tag 的 ZIP 不会自动刷新 - 想让镜像分发“干净”的包,必须由作者打新 tag + 重新触发 Packagist 构建(例如 push 新 commit 并 tag)
为什么私仓用"type": "composer"时exclude失效?
因为 "type": "composer" 源依赖远程 packages.json,而该文件是静态快照,不包含 archive.excludes 或 .gitattributes 信息——它只列出了可用版本和 dist URL。
也就是说,私仓服务器返回的 packages.json 里,每个包的 dist.url 指向一个 ZIP 地址,Composer 下载这个 ZIP 后直接解压,完全不检查其构建时是否应用了排除规则。
- 如果你的私仓 ZIP 是手动打包的,没执行
composer archive或忽略.gitattributes,那 tests/ 就一定在 vendor 里 -
repositories.exclude只影响“当前源是否提供某包”,不改变 ZIP 内容本身 - 真正可控的方式是私仓改用
"type": "package",每个包显式声明dist.url指向已按archive.excludes或.gitattributes构建好的 ZIP
gitattributes export-ignore 在镜像源中是否生效?
对镜像源本身无效,但对最终用户有效——前提是镜像源分发的 dist 包是基于 git archive 构建的。
Packagist 官方构建 dist 包时默认调用 git archive,因此尊重项目根目录下的 .gitattributes 中的 export-ignore 规则;主流镜像源(如阿里云)同步的是 Packagist 已构建好的 ZIP,所以间接继承了该行为。
- GitHub “Download ZIP” 按照
.gitattributes过滤,但镜像源不走这一步——它拿的是 Packagist 打好的包 - 若私仓自行构建 ZIP 却没启用
git archive(比如用zip -r手动打包),.gitattributes就完全被忽略 - 验证方式:下载镜像源提供的某包 ZIP,解压后检查
tests/是否存在;若存在,说明构建环节没读.gitattributes
如何确认某个包的 ZIP 真正排除了 tests/?
不能只看 composer.json 里有没有 archive.excludes,必须验证实际 ZIP 内容。
- 运行
composer install --prefer-dist --verbose,找到下载 URL(形如https://mirrors.aliyun.com/composer/dists/vendor/name/1.2.3.0-zip) - 用
curl -I或浏览器打开该 ZIP URL,下载后unzip -l xxx.zip | grep tests/ - 如果 ZIP 里仍有
tests/,说明要么作者没打新 tag,要么构建流程绕过了.gitattributes或archive.excludes - 注意:某些包把测试类放在
src/下(如src/Tests/),这种无法靠任何排除机制过滤,只能靠 autoload-dev +--no-dev
归根结底,排除不是协议层能力,而是构建动作的结果;镜像源只搬运,不加工。谁控制 ZIP 构建,谁才真正控制“排除”是否落地。











