Composer的archive命令默认打包所有源码文件,包括tests/、docs/、.github/、phpunit.xml等非运行时必需内容;需在composer.json顶层配置archive.excludes数组,仅支持和?通配符,不支持*递归匹配。

archive命令默认打包哪些文件
Composer 的 archive 命令(如 composer archive --format=zip)不会读取 .gitignore,而是依赖内置白名单 + archive.excludes 配置。默认它会打包所有源码文件,包括 tests/、docs/、.github/、phpunit.xml 等非运行时必需内容——这会导致分发包体积膨胀、暴露测试逻辑或 CI 配置。
在composer.json中配置archive.excludes
必须在项目根目录的 composer.json 的顶层(与 require 同级)添加 archive.excludes 字段,值为字符串数组。它支持 glob 模式,但**不支持通配符递归**(** 无效),只认 * 和 ?。
-
"*.md"→ 排除所有 Markdown 文件(如README.md、CHANGELOG.md) -
"tests/*"→ 排除tests/下一级所有内容(但tests/unit/HelperTest.php仍会被包含) -
"tests/**"→ ❌ 无效,会被忽略 -
"vendor/*"→ 虽然 vendor 本就不会被打包,但写上更明确 -
".*"→ 排除所有点开头文件(.gitignore、.editorconfig),但.env.example也会被剔除,需谨慎
示例片段:
{
"name": "my/package",
"archive.excludes": [
"*.md",
"tests/*",
"docs/*",
".gitignore",
".editorconfig",
"phpunit.xml"
]
}
排除深层目录要写全路径或用多条规则
因为 archive.excludes 不支持 **,想排除 tests/unit/ 和 tests/integration/,不能只写 "tests/*" —— 它只匹配 tests/ 下的直接子项,而 tests/unit/HelperTest.php 是两级嵌套,会被保留。必须显式列出:
"tests/unit/*""tests/integration/*""tests/bootstrap.php"
或者更干脆:把整个 tests/ 移到项目外(如用 composer create-project 分离开发依赖),否则靠 archive.excludes 很难覆盖所有测试相关路径。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
验证排除是否生效
执行 composer archive 后不要直接上传,先解压检查。更可靠的是用 --no-interaction -v 查看详细日志:
composer archive --format=zip --no-interaction -v
输出中会出现类似 Excluding tests/HelperTest.php (matches pattern "tests/*") 的提示。若没看到对应行,说明规则没命中——常见原因有:
- 路径大小写不一致(Windows 下易忽略,Linux 区分大小写)
- 规则写了
Tests/但实际目录是tests/ - 用了
**或正则语法(archive.excludes只认简单 glob) -
composer.json格式错误导致字段未被解析(可用composer validate检查)
真正容易被忽略的是:archive 动作发生在 Composer 构建阶段,如果项目用 Monorepo 工具(如 lerna 或 pnpm workspaces)管理,composer archive 仅作用于当前 package 目录,不会自动识别 workspace 结构——这时得手动调整 archive.excludes 覆盖跨包路径。










