离线添加依赖必须提前准备好本地包副本及所有递归依赖,并确保已缓存或通过path仓库配置。推荐用path仓库方式:将含composer.json的包放本地目录,配置repositories为path类型,再require@dev;或迁移vendor+composer.lock及全局缓存。

离线添加依赖前必须确认的几个前提
Composer 本身不支持“纯离线安装新包”,因为 composer require 默认会访问 Packagist 并下载 ZIP 或通过 Git 克隆。所谓“离线添加”,本质是绕过网络请求,靠本地已有资源完成依赖解析与安装。
关键前提是:你已经拥有目标包的完整可运行副本(含 composer.json 和源码),且它的所有依赖(递归)也都已提前下载并缓存好。
常见错误现象:Could not fetch https://repo.packagist.org/packages.json、Failed to download vendor/package: no matching package found —— 这说明 Composer 仍在尝试联网,或本地没有对应包的元数据。
用 path 仓库方式加载本地包
这是最可靠、最可控的离线方案。它让 Composer 把本地目录当做一个私有仓库,跳过远程元数据查询。
操作步骤:
- 把目标包(比如
monolog/monolog)的完整源码(含composer.json)放到项目内某处,例如./packages/monolog - 在项目根目录的
composer.json中添加仓库配置:
{
"repositories": [
{
"type": "path",
"url": "./packages/monolog"
}
]
}
- 执行
composer require monolog/monolog:@dev(注意必须带版本约束,@dev表示接受dev-main或dev-master) - Composer 会软链接或复制该目录到
vendor/,不发任何 HTTP 请求
为什么这样做有效?因为 path 类型仓库不依赖 packages.json 索引,Composer 直接读取本地 composer.json 解析依赖关系。
容易踩的坑:url 必须是相对路径(从项目根目录起算),不能是绝对路径;包名必须和其 composer.json 中的 "name" 完全一致;如果包有子依赖,它们也得用同样方式提供,否则安装仍会失败。
复用已有的 vendor 和 composer.lock
如果你在另一台机器上已完成依赖安装,可以直接迁移整个 vendor/ 目录 + composer.lock 到离线环境。
但要注意:
-
composer install在有composer.lock时默认不联网,但前提是 lock 文件里所有包的dist.url指向的是可访问地址 —— 离线时这个 URL 无意义,Composer 实际走的是dist.shasum校验 + 本地缓存查找 - 所以必须提前在联网机器上运行过
composer install,让包被下载进 Composer 全局缓存(通常位于~/.composer/cache/files/) - 把整个
~/.composer/cache/打包拷贝到离线机相同路径下,再运行composer install才能成功
性能影响:省去重复下载,但首次离线 install 仍需解压和校验,比在线慢一点;兼容性上要求两台机器 PHP 版本、扩展一致,否则 composer.lock 中的平台配置可能触发警告或跳过某些包。
为什么不用 composer archive 或直接 cp vendor?
composer archive 只打包当前项目代码,不包含依赖源码;而直接复制 vendor/ 到另一台机器,在没 composer.lock 或平台不一致时极大概率出问题 —— 比如 ext-gd 缺失导致 intervention/image 的服务提供者报错,但错误信息只显示 Class not found,根本看不出是扩展缺失。
真正容易被忽略的点是:Composer 的离线能力高度依赖“前期准备”。不是“断网后想办法”,而是“联网时就该把 cache、lock、path 结构都配好”。一旦漏掉某个子依赖的本地副本,或者缓存目录权限不对,整个流程就会卡在看似无关的错误里。










