私有源必须配置为 type: "composer",对象存储仅作为 packages.json 和 dist ZIP 的静态托管后端,需确保 URL 可直接访问、MIME 正确、CDN 缓存策略合理,并显式设置 archive.prefix-url 生成绝对 dist.url;客户端须禁用 packagist.org 且私有源排第一,强制使用 --prefer-dist 安装。

私有源必须用 type: "composer",不能配成 vcs 或 path
对象存储(如阿里云 OSS、腾讯云 COS、AWS S3)本身不运行服务,只提供静态文件托管能力,所以它只能作为 Satis、Private Packagist 等工具生成的 packages.json 和 dist ZIP 包的存放后端。这意味着客户端 Composer 必须通过 type: "composer" 类型源访问——它会先请求 packages.json,再按其中 dist.url 下载 ZIP。
常见错误是把对象存储地址误配成 "type": "vcs",结果 Composer 尝试 git clone 一个 HTTP URL,直接报错 Failed to execute git clone --no-checkout;或者配成 path,导致本地路径校验失败且无法跨机器共享。
-
type字段漏写或拼错(比如写成"composor"),整个仓库会被静默忽略,composer diagnose不报错但composer config repositories里看不到 - 对象存储的 bucket 域名必须可被公网/内网直接
curl -I访问,返回200 OK,且 MIME 类型为application/json(对packages.json)或application/zip(对 dist) - 若用 CDN 加速对象存储,需确保缓存策略允许
packages.json的Cache-Control: no-cache或低 TTL(建议 ≤ 60s),否则版本更新后客户端拉不到新包
packages.json 中的 dist.url 必须指向对象存储直链,且带完整协议和域名
Satis 构建时默认生成的 dist.url 是相对路径(如 "dist/mylib-1.2.3.zip"),这在对象存储上会变成 404。你必须在 satis.json 里显式设置 archive.prefix-url,让它拼出绝对 URL:
{
"name": "My Private Repo",
"homepage": "https://packages.example.com",
"archive": {
"prefix-url": "https://oss.example.com/bucket-name",
"directory": "dist",
"format": "zip"
},
"repositories": [{ "type": "vcs", "url": "https://gitlab.example.com/internal/sdk.git" }]
}
构建后检查生成的 packages.json,确认每个包的 dist.url 形如 "https://oss.example.com/bucket-name/dist/mylib-1.2.3.zip",而不是 "dist/..." 或 "http://localhost/..."。
- 如果对象存储开启 Referer 白名单,需放行所有调用方 IP 或关闭 Referer 验证——Composer 下载 ZIP 时不带
Referer头 - 低频读写层的关键在于:ZIP 文件一旦上传就极少变动,所以对象存储可设为“低频访问”类型(如阿里云 IA、AWS S3 Standard-IA),节省约 40% 存储费用,但注意首次下载延迟略高(毫秒级,可接受)
- 别在
dist.url里硬编码临时签名 URL(如带Expires参数的 OSS 签名链接),Satis 不支持动态签发,且composer install不会重试过期链接
客户端必须禁用 packagist.org,且私有源排第一
即使你加了私有源,Composer 默认仍会在最后 fallback 到 packagist.org。如果私有包名(如 internal/logger)恰好和公开包同名,它可能静默装错版本,甚至覆盖你的私有实现。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
正确做法是在项目 composer.json 的 repositories 数组开头声明私有源,并显式关掉默认源:
{
"repositories": [
{
"type": "composer",
"url": "https://packages.example.com"
},
{ "packagist.org": false }
],
"require": {
"internal/logger": "^2.1"
}
}
顺序和 {"packagist.org": false} 必须是数组中独立项,不能塞进前面那个对象里,否则无效。
- 执行
composer config repositories查看当前生效列表,确认你的私有源在第一位、packagist.org显示为false - CI/CD 流水线中容易漏掉这一步,导致测试环境走私有源、生产环境却从 packagist 装包——务必在部署前加
composer validate和composer show internal/logger校验来源 - 若团队混用全局配置(
~/.composer/config.json),优先级高于项目级,可能覆盖项目设置,建议统一用项目级配置
对象存储做低频层时,--prefer-dist 是唯一有效模式
对象存储只存 ZIP,不存 Git 元数据,所以必须强制走 dist 安装路径。任何 --prefer-source 或未指定策略的 composer install 都会失败——Composer 找不到 Git 仓库地址,回退逻辑又因 packagist.org 已关而中断。
所有命令都得带上 --prefer-dist,尤其在 CI 脚本里不能省略:
composer install --no-dev --no-autoloader --prefer-dist
同时确保 composer.json 中没写 "preferred-install": "source" 这类覆盖配置。
- 离线部署时,只需同步对象存储里的
dist/目录到本地cache-files-dir,再运行composer install --prefer-dist --no-network即可,完全不依赖外网 - 对象存储的低频访问类型通常有最小取回量(如阿里云 IA 单次最低取回 64KB),所以小 ZIP 包(
- 别指望对象存储自动清理旧版 ZIP——Satis 不删历史文件,需配合脚本定期
aws s3 ls s3://bucket/dist/ | grep -E '\.zip$' | awk '{print $4}' | xargs -I{} aws s3 rm s3://bucket/{}清理
composer、dist.url 必须是可直连的绝对地址、客户端必须关 packagist 且强制 --prefer-dist。少一个,带宽省不下,还容易装错包。

















