Composer 可以选择仅在开发时加载多个依赖项,因此这些工具不会安装在生产中(在实时服务器上)。这(理论上)对于仅在开发中才有意义的脚本非常方便,例如测试、假数据工具、调试器等。
可行的方法是在 dev 中使用您需要的工具添加一个额外的 require-dev
块:
"require-dev": {
"codeception/codeception": "1.6.0.3"
}
然后(理论上)通过加载这些依赖项
composer install --dev
问题和问题:
Composer 在 2013 年显着改变了 install
和 update
的行为,现在默认安装 require-dev
-依赖项 (!),随意创建带有 require-dev
块的 composer.json 并执行 {5 } 来重现。
由于最常见的部署方式是推送 composer.lock(保存您当前的 composer 设置),然后在生产服务器上执行 composer install
,这也将安装开发内容。
在不安装 -dev 依赖项的情况下部署它的正确方法是什么?
注意:我试图在这里创建一个规范的 Q/A 来澄清奇怪的 Composer 部署。随意编辑这个问题。
composer.lock
永远不应该添加到 Git 存储库中,永远不要。正确的方法是在暂存时使用 composer update 然后将文件同步到生产中(当然,如果一切正常的话)。登台必须是生产环境的精确副本。 composer.lock
应该是 .gitignore
的一部分。
为什么
恕我直言,Composer 现在默认使用 --dev
标志(在安装 和 更新时)是有充分理由的。 Composer 主要在需要行为的场景中运行:
Composer 的基本工作流程如下:
启动一个新项目:composer.phar install --dev,json 和 lock 文件被提交到 VCS。
其他开发人员开始从事该项目:检查 VCS 和 composer.phar install --dev。
开发人员添加依赖项:composer.phar 需要
其他人继续:(结帐和)composer.phar install --dev。
开发人员想要更新版本的依赖项:composer.phar update --dev
其他人继续:(结帐和)composer.phar install --dev。
项目已部署:composer.phar install --no-dev
如您所见,--dev
标志的使用(远)多于 --no-dev
标志,尤其是当从事该项目的开发人员数量增加时。
生产部署
在不安装“dev”依赖项的情况下部署它的正确方法是什么?
那么,composer.json
和 composer.lock
文件应该提交给 VCS。不要省略 composer.lock
,因为它包含有关应使用的软件包版本的重要信息。
执行生产部署时,您可以将 --no-dev
标志传递给 Composer:
composer.phar install --no-dev
composer.lock
文件可能包含有关开发包的信息。这没关系。 --no-dev
标志将确保未安装这些开发包。
当我说“生产部署”时,我指的是旨在用于生产的部署。我并不是在争论 composer.phar install
是否应该在生产服务器上完成,或者在可以审查事情的登台服务器上完成。这不是这个答案的范围。我只是指出如何在不安装“开发”依赖项的情况下composer.phar install
。
无关
--optimize-autoloader
标志在生产中也可能是可取的(它会生成一个类映射,这将加速您的应用程序中的自动加载):
composer.phar install --no-dev --optimize-autoloader
或者当自动部署完成时:
composer.phar install --no-ansi --no-dev --no-interaction --no-plugins --no-progress --no-scripts --optimize-autoloader
如果您的代码库支持它,您可以将 --optimize-autoloader
换成 --classmap-authoritative
。更多信息here
实际上,我强烈建议不要在生产服务器上安装依赖项。
我的建议是检查部署机器上的代码,根据需要安装依赖项(这包括如果代码投入生产,则不安装开发依赖项),然后将所有文件移动到目标机器。
为什么?
在共享主机上,您可能无法访问命令行
即使你这样做了,PHP 可能会在命令、内存或网络访问方面受到限制
可能不会安装存储库 CLI 工具(Git、Svn),如果您的锁定文件记录了检查某个提交而不是将该提交作为 ZIP 下载(您使用 --prefer-source 或 Composer 有没有其他方法可以获得该版本)
如果您的生产机器更像是一个小型测试服务器(想想 Amazon EC2 微型实例),则可能甚至没有足够的内存来执行 composer install
尽管作曲家试图不破坏任何东西,但您对以部分损坏的生产网站结束感觉如何,因为在作曲家安装阶段无法加载一些随机依赖项
长话短说:在您可以控制的环境中使用 Composer。您的开发机器确实符合条件,因为您已经拥有操作 Composer 所需的所有东西。
在不安装 -dev 依赖项的情况下部署它的正确方法是什么?
使用的命令是
composer install --no-dev
这将适用于任何环境,无论是生产服务器本身,还是部署机器,或者是应该进行最后检查的开发机器,以发现是否有任何开发需求被错误地用于真实软件。
该命令不会安装或主动卸载 composer.lock 文件中声明的开发要求。
如果您不介意在生产服务器上部署开发软件组件,则运行 composer install
可以完成相同的工作,但只会增加移动的字节数,并且还会创建更大的自动加载器声明。
app-1.34.phar
等)。有一个单独的机制被通知并决定何时获取该文件,将其传输到何处以及如何处理它。一些团队选择将 phar 放在服务器上后对其进行解包,而一些团队则按原样运行它。它为我们部署的稳定性和可重复性提供了很大的信心。
现在默认启用 require-dev
,对于本地开发,您可以在没有 --dev
选项的情况下执行 composer install
和 composer update
。
当您想要部署到生产环境时,您需要确保 composer.lock
没有来自 require-dev
的任何包。
你可以这样做
composer update --no-dev
使用 --no-dev
在本地进行测试后,您可以将所有内容部署到生产环境并基于 composer.lock
进行安装。此处再次需要 --no-dev
选项,否则 composer 会说 “锁定文件不包含 require-dev 信息”。
composer install --no-dev
注意:小心任何有可能在开发和生产之间引入差异的东西!我通常会尽可能避免 require-dev,因为包含开发工具并不是很大的开销。
composer.lock
的开发依赖项。您只需运行 composer install --no-dev
,您将只安装常规依赖项 - 事实上,Composer 还将在此步骤中删除任何开发依赖项。
composer.lock
中有开发依赖项(并可能影响非开发包的版本),那么我想更新它以反映它在生产中的情况。这也迫使您在生产环境中运行 composer install --no-dev
,因为 composer install
会出错。从技术上讲,我认为您是对的;这不是必需的,但这是我喜欢的额外安全级别。
dev/tool
和 prod/lib:~1.0
。最新的 prod/lib 是 1.3,但 dev/tool 还需要 prod/lib:1.1.*
。结果:您将安装版本 1.1.9(最新的 1.1.x 分支)并在开发过程中使用它。我会说只更新 --no-dev
是不安全的,因此包括最新的 prod/lib 1.3 并假设一切正常而无需测试。由于缺乏开发/工具,因此可能无法进行测试。我会假设因为在生产中不需要 dev/tool,所以不应该推出它,但是软件必须使用 prod/lib 1.1.9。
--no-dev
,那么您需要在本地测试它,正如我在答案中提到的那样。不过,我仍然建议不要使用 --no-dev
。
composer update
,然后做一些开发,然后做 composer update --no-dev
,然后做发布测试,然后推送到生产并做 composer install --no-dev
。两个问题:1. 我无法在没有开发依赖项的情况下测试版本,以及 2. 我无法在生产环境中安装例如 Git。
我认为最好使过程自动化:
在您的 git 存储库中添加 composer.lock 文件,确保在发布时使用 composer.phar install --no-dev,但是在您的开发机器中,您可以使用任何 composer 命令而不用担心,这不会投入生产,生产将在锁定文件中建立其依赖关系。
在服务器上检查此特定版本或标签,并在替换应用程序之前运行所有测试,如果测试通过,则继续部署。
如果测试依赖于 dev 依赖,因为 composer 没有测试范围依赖,一个不太优雅的解决方案可以使用 dev 依赖(composer.phar install)运行测试,删除供应商库,运行 composer.phar install - -no-dev 再次,这将使用缓存的依赖项,因此速度更快。但是,如果您知道其他构建工具中的范围概念,那将是一个 hack
自动化这个,忘记其余的,去喝啤酒:-)
PS.:正如下面的@Sven 评论,不签出composer.lock 文件不是一个好主意,因为这将使composer install 作为composer update 工作。
您可以使用 http://deployer.org/ 实现自动化,这是一个简单的工具。
composer.lock
将使 composer install
表现得像 composer update
。因此,您部署的版本不是您开发的版本。这可能会产生麻烦(鉴于最近在 Composer 中使用“替换”解决了唯一的安全问题,因此更是如此)。你不应该在无人看管的情况下运行 composer update
而不验证它没有破坏任何东西。
在生产服务器上,我将 vendor
重命名为 vendor-<datetime>
,并且在部署期间将有两个供应商目录。
HTTP cookie 导致我的系统选择新的供应商 autoload.php
,在测试之后,我在它们之间进行了完全原子/即时切换,以禁用旧的供应商目录以处理所有未来的请求,然后在几天后删除以前的目录。
这避免了我在 apache/php 中使用的文件系统缓存引起的任何问题,并且还允许任何活动的 PHP 代码继续使用以前的供应商目录。
尽管有其他建议反对它,但我个人在服务器上运行 composer install
,因为这比我的暂存区域(我的笔记本电脑上的 VM)的 rsync 更快。
我使用 --no-dev --no-scripts --optimize-autoloader
。您应该阅读每个文档以检查这是否适合您的环境。
不定期副业成功案例分享
--optimize-autoloader
中的好点。还请考虑--classmap-authoritative
- 从此处的文档 getcomposer.org/doc/03-cli.md 您可以看到:“仅从类映射中自动加载类。隐式启用 --optimize-autoloader”,因此如果您知道类“存在”,则可以使用,这可能除非您动态生成类,否则应该在您的 prod 环境中发生。composer.json
中添加optimize-autoloader
:{"config": { "optimize-autoloader": true } }