composer archive 不支持导出所有依赖包源码,仅打包当前项目代码;需通过配置 "prefer-source": true 并结合 git archive 或 Packagist API 下载源码实现完整备份。

composer archive 命令本身不支持导出所有依赖包的源码
直接运行 composer archive 只能打包当前项目(即 composer.json 所在目录)的代码,它**不会自动包含 vendor 下的依赖包源码**。这是很多人误以为“一键打包全部依赖”的根本原因——命令设计上就不做这事。
如果你真正想做的是:把项目 + 所有已安装的第三方包(含其完整源码、.git 目录、未提交修改等)一起归档备份,得换思路。
用 git archive + vendor 递归打包更可靠
前提是项目和所有依赖包都用 git 管理(Composer 默认 install 的包大多如此)。核心逻辑是:先确保 vendor 已完整安装,再对每个包单独执行 git archive。
- 先运行
composer install --no-dev或composer install,确保vendor/齐全且含 .git 目录(某些包若被 shallow clone 或用 zip 安装则无 .git,需提前配置"prefer-source": true) - 在
composer.json中添加配置避免 zip 回退:{ "config": { "prefer-source": true } } - 手动打包示例(Linux/macOS):
#!/bin/bash mkdir -p backup-$(date +%Y%m%d) cp -r ./* backup-$(date +%Y%m%d)/ rm -rf backup-$(date +%Y%m%d)/vendor mkdir -p backup-$(date +%Y%m%d)/vendor
for pkg in vendor//; do [ -d "$pkg/.git" ] && ( cd "$pkg" git archive --format=zip --prefix="$(basename $(dirname $pkg))/$(basename $pkg)/" HEAD > /tmp/$(basename $pkg).zip unzip -q /tmp/$(basename $pkg).zip -d ../backup-$(date +%Y%m%d)/vendor/ rm /tmp/$(basename $pkg).zip ) done
composer show -i 输出包列表后逐个下载源码(离线友好)
适合无法保证 vendor 包含 .git 的场景(比如 CI 环境或禁用了 source 模式)。用 composer show -i 列出所有已安装包及其版本,再调用 Packagist API 或 GitHub/GitLab 直链下载对应 tag 的源码 zip。
-
composer show -i --format=json输出结构化数据,可解析出name和version - GitHub 包通用下载地址格式:
https://github.com/{user}/{repo}/archive/refs/tags/{version}.zip(注意部分版本号需转义,如v1.2.3→1.2.3) - 非 GitHub 包需查其
source.url字段(用composer show {vendor/name} --all查),再拼接对应平台规则 - 这个流程没法还原本地修改,也不含 dev-master 的未打 tag 提交,属于“干净但不完整”的备份
真正可靠的备份不是靠单条命令,而是靠配置+流程
最常被忽略的一点:你是否真的需要“所有包的源码”?多数生产备份只需 composer.lock + composer.json + 自己写的代码。依赖包本身可随时重装。
但如果必须保留原始源码(例如审计、离线审查、patch 跟踪),那就必须提前干预 Composer 行为:
- 全局或项目级设
"prefer-source": true - 禁用
"discard-changes": true(否则 git 修改会被清掉) - 定期运行
composer update --lock并提交composer.lock,保证可重现性 - 不要依赖
composer archive做依赖备份——它压根不是为这设计的
一旦漏掉 prefer-source,vendor 里全是 zip 解压出来的裸文件,连 commit hash 都没了,后面怎么溯源都是徒劳。










