composer archive默认打包项目源码(含composer.json、readme.md等元数据),排除.git、vendor、node_modules、.env、composer.lock等,但不自动排除tests/、docs/、.env.example等非运行必需文件。

archive 命令默认打包哪些文件?
Composer 的 archive 命令不会简单地把整个项目目录 zip 起来,而是基于 composer.json 中的 autoload、require 和 scripts 等字段推导“运行时必需文件”,再叠加一些默认包含/排除规则。它默认会排除 .git、vendor/composer/installed.json、所有测试文件(如 *Test.php)、phpunit.xml、composer.lock(除非显式启用 --include-lock),但**不会自动排除开发专用配置、本地.env 文件、调试工具或未声明的源码目录**。
如何用 exclude 列表精准剔除非生产文件?
archive 支持 --exclude 参数,可多次使用,每项是一个 glob 模式(不是正则)。关键点在于:路径匹配基于项目根目录,且不递归展开——也就是说,--exclude "tests/*" 会排除 tests/ 下所有内容,但 --exclude "tests" 只匹配名为 tests 的文件(而非目录)。
- 必须写相对路径,从项目根开始,比如
--exclude ".env.local"、--exclude "docker/**" - 通配符只支持
*和**:**匹配任意层级子目录,*只匹配当前层 - 多个
--exclude会被合并处理,顺序无关;但若某路径被包含又被排除,排除优先 - 常见误写:
--exclude ".env*"会漏掉.env.example(因为*不跨目录),应写成--exclude ".env*"+--exclude ".env.*"或更稳妥的--exclude ".env*"和--exclude ".env.*"
生产发布时最该排除的几类文件
实际部署中,以下几类最容易引发安全或运行问题,建议固化到 CI 脚本中:
-
--exclude ".env"和--exclude ".env.*":防止敏感配置泄露(即使你用了dotenv,.env 文件本身也不该进包) -
--exclude "phpunit.xml*"、--exclude "phpcs.xml*"、--exclude "phpstan.neon":静态分析和测试配置对运行时无用,且可能暴露内部结构 -
--exclude "tests/**"、--exclude "Tests/**"、--exclude "test/**":大小写敏感,PHP 项目常混用 -
--exclude "docker/**"、--exclude "deploy/**":编排和部署脚本不属于应用代码 -
--exclude "CHANGELOG.md"、--exclude "CONTRIBUTING.md":文档类文件体积大、无运行价值
archive 打包后怎么验证排除是否生效?
别依赖肉眼检查 zip 内容,用 unzip -l 加管道过滤更快:
composer archive --format=zip --file=app.zip --exclude=".env" --exclude="tests/**" unzip -l app.zip | grep -E '\.(env|xml|md|yml)$|tests/|docker/'
如果输出为空,说明排除成功;若有残留,就说明 glob 模式没覆盖到(比如 .env.production 没被 .env* 匹配到)。另外注意:archive 不校验文件是否存在——--exclude "nonexistent/" 不报错,也不会影响结果。
真正容易被忽略的是:排除列表对 vendor/ 目录无效——它只作用于项目根及子目录,vendor 中的文件由 Composer 自身依赖解析决定,想精简 vendor 需改用 --no-dev 或提前 install --no-dev。











