composer怎么在离线环境下模拟packagist响应?

1次阅读

packagist.org 响应本质是 composer 协议兼容的结构化元数据服务,含严格校验的 packages.json、带签名的 notify 字段及依赖图谱;离线必须用 satis 等语义级工具生成合法镜像,而非简单 mock http

composer怎么在离线环境下模拟packagist响应?

packagist.org 响应本质是什么?

Composer 离线时卡在 composer installcomposer update,根本原因是它默认要请求 packagist.org/packages.json 和各包的 dist / source 元数据。这些不是“随便伪造一个 JSON 就行”,而是有固定结构、签名(部分带 packages.jsonnotify 字段)、以及依赖关系图谱。

离线模拟的关键不是“挡掉网络请求”,而是让 Composer 认为它正连着一个合法的 Packagist 镜像——哪怕这个镜像只返回本地已有的包信息。

用 satis 构建最小可用离线仓库

satis 是官方推荐的静态包仓库生成工具,适合离线场景。它不提供实时服务,但能生成 Composer 可直接读取的 packages.json 和压缩包链接(指向本地文件或内网路径)。

  • 必须提前在有网环境运行 satis build,把所需包及其所有依赖递归下载并快照
  • 生成的 packages.json 要放在 Web 服务器根目录(如 nginx/var/www/html),或用 php -S 快速起服务
  • composer.json 中必须显式配置仓库:
    { "repositories": [   {     "type": "composer",     "url": "http://localhost:8000"   } ] }
  • satis.json 中禁用 archiveskip-dev(否则 dev 分支包丢失),并确保 require-all 设为 true 或明确列出所有需要的包名+版本约束

常见错误:直接把 vendor 目录当仓库;或者只复制了 vendor/foo/bar 但没生成对应的 packages.json 条目 —— Composer 根本看不到这个包。

为什么不能只改 hosts + mock HTTP 响应?

有人想用 hostspackagist.org 指向本地 127.0.0.1,再用 Python/PHP 写个简单 HTTP handler 返回假 JSON。这会失败,因为:

  • Composer 对 packages.json 有强校验:字段如 packagesnotify-batchproviders 缺一不可,且嵌套层级严格
  • 各包的 dist URL 必须可访问(即使本地 file:// 协议也需开启 allow_url_fopen,且 Composer 3.x 已默认禁用)
  • 如果用了 composer.lock 中的 content-hash,而生成的 packages.json 结构微小不一致(比如字段顺序、空格、多余逗号),就会触发 hash 不匹配报错:Content hash mismatch

所以,绕过 Packagist 的唯一可靠路径是用 satis 或 private Packagist(如 Toran Proxy)这类理解 Composer 协议语义的工具,而不是 HTTP 层面的“假装”。

离线环境必须预装的依赖项

离线机器上,光有 packages.json 不够。Composer 还要能:

  • 解压 .zip / .tar.gz 包:确认系统已安装 unziplinux/macos)或对应解压工具(windows 需额外配置 7z 并在 composer.json 中设 "archive": {"format": "zip"}
  • 执行 install 时的脚本(如 post-install-cmd):确保 PHP 扩展(如 zlibopenssl)已启用,否则解包或验证签名失败
  • 若项目含 platform 配置(如 "php": "8.1.0"),离线机器的 PHP 版本必须严格匹配,否则 composer install 会跳过包安装并报 Your platform matches the required version 类似提示(实际是反向逻辑,容易误读)

最常被忽略的是:satis 生成的 dist URL 默认是 https://...,离线时得批量替换成 file:///path/to/dist/,并且该路径必须对运行 Composer 的用户可读。

text=ZqhQzanResources