composer本地缓存命中仅依赖文件存在性与哈希匹配,不发起http请求验证远端变更,故无304复用;元数据复用取决于本地repo/目录下json文件是否被gc清理或过期,与nginx等代理层的304响应无关。

本地缓存命中只看文件存在性,不走HTTP 304
Composer 本地缓存根本不会发 HTTP 请求去验证远端元数据是否变更,也就不存在“304 Not Modified”复用一说。所谓“命中”,是 Composer 在执行 composer install 时,直接检查 ~/.composer/cache/files/ 下是否存在与 composer.lock 中 dist.shasum 完全匹配的 ZIP 文件;若存在且非空,就跳过下载,直接解压。元数据(如 packages.json)同样只比对本地 ~/.composer/cache/repo/ 中对应文件的修改时间与哈希,不向镜像源发起任何 HEAD 或 GET 请求。
为什么你看到的“304”不是Composer触发的
你在 curl -I 或浏览器开发者工具里看到的 304 响应,来自 Nginx / CDN 层对镜像源的代理缓存行为,和 Composer 进程本身无关。Composer CLI 发出的请求默认带 If-Modified-Since 和 If-None-Match 头,但 packagist.org 及主流镜像(阿里云、腾讯云)均返回 Cache-Control: no-cache 或 max-age=0,强制客户端不缓存——所以 Composer 每次都会收到 200 响应并覆盖本地元数据缓存,哪怕内容没变。
- 想让元数据“复用”,必须靠 Nginx 代理层主动忽略上游
Cache-Control并设置自己的proxy_cache_valid - Composer 自身无 304 回退逻辑,
--offline模式下它连 HTTP Client 都不启动 -
composer update --dry-run输出里的 “Using version x.y.z for pkg” 不代表复用了远程响应,只是解析了本地 lock + cache 后的推断结果
真正影响“元数据复用”的是 cache-dir 和 gc 策略
元数据缓存是否有效,取决于 ~/.composer/cache/repo/ 目录下的 JSON 文件是否被 GC 清理掉,以及其内容是否与当前 composer.lock 解析需求匹配。GC 触发条件有两个:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
cache-files-ttl:默认 6 个月,控制元数据文件“最后访问时间”超期后被删(注意:是访问时间,不是创建时间) -
cache-files-maxsize:当整个cache/目录超过阈值,Composer 会按“最后访问时间”排序,删除最旧的文件(包括 repo/ 下的 JSON) - 手动运行
composer clear-cache会清空 repo/ 子目录,下次install必须重拉所有元数据
如果你发现频繁重拉 packages.json,先查 ls -lt ~/.composer/cache/repo/,再确认 composer config --global cache-files-ttl 是否被设得太小。
CI 中稳定复用元数据的实操要点
在 GitHub Actions 或 GitLab CI 中,光缓存 ~/.composer/cache/files/ 不够,repo/ 目录同样需要持久化,否则每次 job 都得重拉顶层元数据(如 packages.json),拖慢首包解析速度。
- 缓存 key 必须包含
composer.lock的 SHA256,而不是仅用 PHP 版本——lock 文件变更会导致元数据需求完全不同 - 挂载路径要完整:GitHub Actions 的
cacheaction 应指定path: ~/.composer/cache,而非子目录 - 避免在 job 开头执行
composer clear-cache,这是常见反模式——它把刚恢复的缓存又清空了 - 如果使用自建 Nginx 镜像代理,可配合
proxy_cache_valid 200 1h+proxy_ignore_headers Cache-Control让元数据在代理层缓存 1 小时,减少对上游的穿透请求
本地缓存机制本质是“静态文件复用”,不是“动态协商缓存”。理解这点,才能避开把 Nginx 配置、HTTP 协议细节和 Composer 内部逻辑混为一谈的坑。










