Composer本地包安装超时的根本原因是其对file://协议仓库仍启用HTTP超时逻辑,且默认不跳过symlink扫描和autoload生成;正确解法是使用path类型仓库并启用symlink模式,同时禁用prefer-dist并清除缓存。

本地包安装超时,不是网络问题,而是 Composer 默认把 path 类型仓库当远程源一样走 HTTP 下载流程——哪怕包就在同一台机器的 ../my-package 目录里,它也会尝试用 file:// 协议拉 ZIP、解压、校验,过程中仍受 process-timeout 和 http-basic-timeout 限制,尤其在 WSL2、Docker 或 NTFS 挂载卷上 I/O 延迟高,极易卡在 Downloading file:///xxx。
为什么 composer require "vendor/name":dev-main" --repository-url=file:///path/to/repo 还会超时
根本原因是:Composer 对 file:// 协议仓库仍启用完整 HTTP 超时逻辑(包括 DNS 解析模拟、TLS 握手跳过但等待首字节逻辑仍在),且默认不跳过 symlink 扫描和 autoload 生成阶段的深度递归。常见现象是命令停在 Downloading file:///.../dist.zip 或卡在 Generating autoload files 后无响应。
-
http-basic-timeout对file://请求也生效,60 秒内若 ZIP 生成慢或磁盘响应延迟高,直接中断 - 即使本地路径存在,Composer 仍会尝试下载 dist ZIP(而非直接 copy source),若
dist配置缺失或archive脚本执行慢,就会卡住 - WSL2 下访问 Windows 文件系统(
/mnt/c/...)时,file://协议性能极差,首字节延迟常超 500ms
改用 path 类型仓库 + symlink 模式绕过下载
这才是本地包开发的正确姿势:让 Composer 直接软链接目录,跳过所有下载、解压、校验环节。必须在项目 composer.json 中显式声明仓库类型为 path,并设 options.symlink 为 true。
- 在项目
composer.json的repositories字段添加:
{
"repositories": [
{
"type": "path",
"url": "../my-package",
"options": {
"symlink": true
}
}
]
}
- 运行
composer require vendor/name:dev-main(注意版本必须匹配my-package/composer.json中的"version"或使用"@dev") - 成功后
vendor/vendor/name是指向../my-package的符号链接,修改即实时生效,无任何超时风险 - 若报
Could not find a matching version,检查my-package/composer.json是否有"version": "dev-main"或去掉该字段让 Composer 自动识别分支
必须禁用 prefer-dist 并清空缓存
即使用了 path 类型,Composer 仍可能因缓存残留强行走 dist 流程。全局或项目级开启 prefer-dist 会覆盖 path 行为,导致回退到 ZIP 下载。
- 确认未启用:
composer config -g prefer-dist应输出false或空;若为true,执行composer config -g prefer-dist false - 项目级检查:
composer config prefer-dist,同样设为false(去掉-g) - 强制清除缓存:
composer clear-cache,否则旧的packages.json元数据可能误导解析流程 - 删除
vendor/和composer.lock后重试,避免 lock 文件锁定错误的 dist 引用
Windows/WSL2 用户额外注意文件协议路径写法
在 WSL2 中用 file:// 协议指向 Windows 路径(如 file:///mnt/c/dev/my-package)几乎必超时。此时唯一可靠方案是统一用 Linux 原生路径 + path 类型。
- 把包和项目都放在 WSL2 的
/home/user/下(如/home/user/my-project和/home/user/my-package),用相对路径"../my-package" - 绝对路径写法必须是
"/home/user/my-package",不能带file://前缀 - Windows 原生 Git Bash 或 CMD 中,确保 PHP 可读取该路径(NTFS 权限、防病毒软件拦截、长路径限制)
- 若必须跨系统访问,改用
git类型仓库:"type": "git", "url": "file:///c:/dev/my-package",但需确保该目录是合法 Git 仓库(含.git)
最易被忽略的是缓存残留和 prefer-dist 的隐式覆盖——哪怕 path 配置完全正确,只要 composer.lock 里还记着上次失败的 dist 引用,或者全局开了 prefer-dist,Composer 就会无视 symlink 直接去下载 ZIP,然后在 60 秒后安静中断。


















