各位同学,把手里的螺丝刀、键盘、甚至是刚泡好的速溶咖啡都先放一放。今天我们不谈复杂的架构设计,也不聊晦涩的算法,我们来聊聊每一个 PHP 开发者——从刚入行的小白,到头发稀疏的大佬——都曾痛彻心扉、想要把电脑屏幕砸个洞的那个话题:
Composer 依赖安装速度慢。
说实话,每次看到那个熟悉的 Loading packages… 界面,我都感觉自己不是在写代码,而是在给一只老乌龟喂食。进度条走一步停三步,仿佛它不是在下载文件,而是在进行一场跨越太平洋的算力马拉松。
作为一名在 PHP 领域摸爬滚打多年的“老油条”,我今天要给大家开一堂公开课。我们不整虚的,直接从根源上剖析为什么它会慢,然后用几把“大杀器”把它变得像闪电一样快。
准备好了吗?让我们开始今天的“加速之旅”。
第一部分:为什么会慢?—— 哪怕是乌龟也有起飞的梦想
首先,我们要搞清楚,这个“慢”到底是从哪来的。这就像你要去吃火锅,餐厅(Packagist.org)在地球的另一端(美国),而你在亚洲。而且,这顿饭的食材还得经过海关(CDN),甚至还得经过你那不争气的本地网络运营商。
1. 服务器距离:
Composer 的官方仓库 packagist.org 虽然现在也有 CDN,但在高峰期,它还是那个矗立在海对面的“大西洋堡垒”。当你运行 composer install 时,它默认就是去这儿拉数据。如果你的网络连接到国际出口慢,那这就不是等待,是在忏悔。
2. 依赖树的结构:
这更像是俄罗斯套娃。你的项目依赖 A,A 依赖 B,B 依赖 C… C 又依赖 D。这是一个庞大的树状结构。Composer 必须把树里的每一个节点都“访问”一遍,下载,解压,解析。如果你依赖的包里还包含几十个子依赖,那这等待时间简直就是一场漫长的刑期。
3. 网络环境:
如果你是在国内,且没有配置代理,那简直是在用 2G 网络连卫星。下载大文件时的“握手”失败和“超时重连”,更是让人抓狂。
所以,解决方案的核心只有一个:缩短物理距离,或者找个替身帮忙。
第二部分:国内的“外卖联盟”——配置国内镜像
既然官方仓库太远,那我们就用国内的。这就像你点外卖,与其飞过去吃,不如让隔壁小区的商家送过来。国内有几大巨头提供镜像服务,我们一个个来试。
1. 阿里云镜像(老牌强者)
阿里云的 Composer 镜像可以说是目前最稳定、最常用的选择。
方法 A:临时使用(Command Line One-liner)
如果你只是偶尔想装个包,不想改全局配置,可以直接在命令行里指定。
composer install --prefer-dist --optimize-autoloader --no-dev https://mirrors.aliyun.com/composer/
解析:
--prefer-dist:Composer 默认会从 Git 拉代码,这很慢。这个参数告诉它,如果包有压缩包,优先下载压缩包,就像你去超市买可乐而不是让厂家现场灌装一样快。--optimize-autoloader:后面我们会细说,这个是加速加载的关键。--no-dev:开发环境可以不装,发布时用,省去装测试包的时间。
方法 B:全局配置(推荐)
每次都写网址太麻烦了,我们要把它变成 Composer 的“默认习惯”。打开终端,输入:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
解析:
-g:Global(全局)。意思是“大爷,把这个规矩定死,以后我都按这个来,别再让我去官网找饭吃了”。repo.packagist:这是告诉 Composer,把官方的 Packagist 仓库替换成阿里云的这个地址。
配置完之后,你再次运行 composer install,你会发现进度条仿佛被打了鸡血,瞬间飞驰。
2. 腾讯云镜像(稳健可靠)
有时候阿里云那个“大拇指”图标太大(指流量占用),你可以试试腾讯云。
composer config -g repo.packagist composer https://mirrors.cloud.tencent.com/composer/
3. 华为云镜像(备胎之王)
作为备选方案,如果你发现前两家都挂了,或者网络波动,华为云通常是最后的选择。
composer config -g repo.packagist composer https://repo.huaweicloud.com/repository/php/
高级技巧:回退策略
有了镜像,我们是不是就完全不能去官网了?万一阿里云镜像里没有某个国外的私有包怎么办?
Composer 允许你配置多个仓库。我们可以配置一个“主仓库”(国内镜像),再配置一个“备用仓库”(官方)。
在你的 composer.json 文件中,找到 repositories 部分,这样写:
{
"repositories": [
{
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/"
},
{
"type": "vcs",
"url": "[email protected]:your-username/your-private-repo.git"
}
],
"require": {
"your/project": "*"
}
}
解析:
Composer 会先去阿里云找,找不到再去 Git 仓库找。这叫“曲线救国”。
第三部分:Autoloader 优化 —— 别让你的大脑过载
当你解决了网络速度问题,以为天下太平了,结果 composer dump-autoload 还是很慢,或者生成的 vendor/autoload.php 加载项目代码时卡顿。
这是因为 Composer 默认生成的是 PSR-0 和 PSR-4 的自动加载规则。这种规则就像是一个刚入学的图书管理员,他记不住书在哪个架子上,每次你要一本书,他都要翻遍整个图书馆的目录,问你:“先生,请问您要哪个目录下的书?”
我们要把这个图书管理员换成“扫地机器人”。
1. composer dump-autoload -o
这是最简单的优化命令。
composer dump-autoload -o
发生了什么?
它会生成一个 vendor/composer/autoload_psr4.php 和一个 vendor/composer/autoload_classmap.php。
-o 参数会生成一个 Classmap(类映射表)。这相当于给所有的类文件建立了一个“字典”。当你引入文件时,Composer 不再扫描目录,而是直接查字典:Class X -> File Y。速度提升非常明显,甚至能提升 50%。
2. composer dump-autoload -p
如果你想追求极致,用这个。
composer dump-autoload -p
解析:
-p 会同时生成 PSR-4 的 Classmap,并且压缩它。这个 Classmap 是一个 PHP 数组,如果项目文件特别多,这个数组会非常巨大。-p 会用 gzencode 把它压缩,减小文件体积,从而加快 PHP 引擎的读取速度。
注意: -p 需要 PHP 支持 zlib 扩展,但绝大多数现代 PHP 环境都支持。
3. 避免重复加载
确保你的 composer.json 里没有循环依赖,也不要 require 一个已经在 autoload 里声明的命名空间。如果逻辑允许,尽量减少 composer update 的频率,只在必要时更新。
第四部分:代理 —— 也就是所谓的“穿墙术”
有时候,即使我们配置了国内镜像,有些包(特别是国外的私有 Git 仓库或者特定的插件)还是会提示连接超时。这时候,你需要的不是镜像,而是一条通往大洋彼岸的高速隧道——VPN。
但是,你不能直接给 Composer 开 VPN。我们需要设置 HTTP 代理。
场景: 假设你使用的是 Clash 或 V2Ray,本地代理端口是 7890。
1. 全局代理配置
composer config --global http-proxy http://127.0.0.1:7890
composer config --global https-proxy http://127.0.0.1:7890
composer config --global no-proxy localhost,127.0.0.1
解析:
http-proxy和https-proxy:指明路条。no-proxy:非常重要!告诉 Composer,“对于本地请求(比如你本地的文件读写),别走代理,直接走本地,否则你会卡死。”配置localhost和127.0.0.1是必须的。
2. SSH 代理(进阶玩家)
如果你在服务器上部署,没有图形界面,用 HTTP 代理可能不生效。这时候,你需要用 SSH 代理跳板。
假设你有一台国外的服务器,或者你有 SSH 访问权限。你可以在 composer.json 中配置 vcs 类型,让它走 SSH。
{
"repositories": {
"my-private-repo": {
"type": "vcs",
"url": "[email protected]:your-username/your-repo.git"
}
}
}
这叫“曲线救国”。只要你能 SSH 上去,代码就能拉下来。虽然比 HTTP 慢一点,但比网络不通要强多了。
第五部分:缓存与清理 —— 像打扫房间一样整理硬盘
有时候,慢不是网络的问题,是本地“垃圾”太多。
1. Composer 缓存
Composer 会缓存下载的包,下次安装时如果版本没变,它会直接用缓存。但如果缓存文件损坏或者太大,它反而会乱。
# 查看缓存位置
composer config -g cache-files-dir
# 清理缓存
composer clear-cache
2. 缓存特定包
有时候你只需要更新某一个包。你可以先锁定这个包,然后只更新它。
composer require vendor/package --update-with-all-dependencies
或者更精确地:
composer update vendor/package --prefer-dist --optimize-autoloader
这就像你去饭店吃饭,不需要点满桌菜,只吃你喜欢的那个菜,上菜速度会快很多。
第六部分:Docker 场景 —— 容器里的速度战
很多同学现在都用 Docker。在 Dockerfile 里安装 Composer 依赖,如果网络不好,构建镜像会非常慢,甚至导致 CI/CD 流水线失败。
这时候,我们需要在 Docker 构建前,就把 Composer 镜像设置好。
Dockerfile 示例:
FROM php:7.4-fpm
# 1. 设置国内镜像源(在安装依赖之前)
RUN composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
# 2. 复制 composer.json 和 composer.lock
COPY composer.json composer.lock ./
# 3. 安装依赖。注意这里用 --no-scripts,因为 install 的时候会触发 scripts
RUN composer install --no-scripts --no-dev --optimize-autoloader --prefer-dist
# 4. 复制源代码
COPY . .
# 5. 生成 autoload(如果需要)
RUN composer dump-autoload -o
关键点:
composer.json和composer.lock必须先复制。因为安装依赖需要读取这两个文件。如果在复制整个项目后再安装,那么项目中新增的依赖就会被忽略(除非你用 update)。--no-scripts:默认情况下composer install会运行脚本(比如修改权限、生成常量等)。在 Docker 构建环境中,很多时候这些脚本是没用的,跳过它们可以节省几秒钟。
第七部分:终极方案 —— 私有仓库代理
如果你是一个大公司的开发者,你们有很多内部开发的 PHP 库,这些库发布在私有的 GitLab 或自建的服务器上。直接从私服拉取肯定比从国外快,但是如果私服也不稳定呢?
这时候,你需要搭建一个 Composer 私有仓库代理。
虽然搭建代理(比如使用 Aliyun Artifactory 或 Satis)比较复杂,需要写配置文件,但这是解决“依赖地狱”和“速度慢”的终极手段。你可以把所有的依赖(官方的、私有的、第三方的)都聚合到一个内网服务器上,让 Composer 像访问本地文件一样去访问。
Satis 简单配置示例 (satis.json):
{
"name": "my-company/vendor-repo",
"description": "Internal Composer Repository for My Company",
"require": {
"php": ">=7.0"
},
"repositories": [
{ "type": "vcs", "url": "[email protected]:company/library-a" },
{ "type": "vcs", "url": "[email protected]:company/library-b" }
],
"minimum-stability": "stable",
"autoload": {
"psr-4": {
"Company\": "src/"
}
}
}
然后通过 php bin/satis build 生成一个静态的包文件。以后安装时,直接指向这个静态文件。这就把网络请求降维打击成了本地文件读取。
总结与“避坑”指南
好了,今天的讲座接近尾声。我们来回顾一下今天学到的几招“独门绝技”:
- 重拳出击(镜像): 终极答案永远是
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/。把它加进你的.bashrc或.zshrc里,甚至可以在 CI 脚本里执行它,作为入职第一件事。 - 精兵简政(Optimize): 养成
composer dump-autoload -o的习惯。看着那个生成 Classmap 的进度条飞快划过,你会感到一种莫名的治愈感。 - 借力打力(Proxy): 当镜像失效,使用 SSH 或 HTTP 代理作为救急方案。
- 全局治理(Docker & Cache): 在构建环境里固化配置,不要让网络波动毁了你的部署流程。
最后,给大家几点“反直觉”的建议:
- 不要频繁运行
composer update: 除非你确实改了依赖版本。composer update会重新解析整个依赖树,那速度绝对能让你怀疑人生。绝大多数时候,用composer install就够了。 - 善用
composer.lock: 你的团队里有人把composer update写在 CI 里吗?如果有,请立刻让他去面壁。composer.lock就像高速公路的限速标志,保证所有人跑的速度是一致的,避免因为某个人把包升级了导致整个项目崩坏。 - 不要迷信国外的教程: 很多老外写的教程还在教你用国外的代理或者配置,如果你在国内,直接用国内的方案,那是降维打击,效率翻倍。
好了,今天的“Composer 加速特训营”就到这里。现在,请打开你的终端,运行 composer install。希望这次,你能看到那个进度条以 100% 的速度瞬间走完。
别客气,请享用这份速度带来的快乐。