ChatGPT解决这个技术问题 Extra ChatGPT

使用 Composer 的开发/生产切换时如何正确部署?

Composer 可以选择仅在开发时加载多个依赖项,因此这些工具不会安装在生产中(在实时服务器上)。这(理论上)对于仅在开发中才有意义的脚本非常方便,例如测试、假数据工具、调试器等。

可行的方法是在 dev 中使用您需要的工具添加一个额外的 require-dev 块:

"require-dev": {
    "codeception/codeception": "1.6.0.3"
}

然后(理论上)通过加载这些依赖项

composer install --dev

问题和问题:

Composer 在 2013 年显着改变了 installupdate 的行为,现在默认安装 require-dev-依赖项 (!),随意创建带有 require-dev 块的 composer.json 并执行 {5 } 来重现。

由于最常见的部署方式是推送 composer.lock(保存您当前的 composer 设置),然后在生产服务器上执行 composer install,这也将安装开发内容。

在不安装 -dev 依赖项的情况下部署它的正确方法是什么?

注意:我试图在这里创建一个规范的 Q/A 来澄清奇怪的 Composer 部署。随意编辑这个问题。

@all:不知道赏金在哪里:(我将开始另一种方法。
如果您不积极奖励它,并且没有答案被接受或获得足够的赞成票,那么没有人会获得赏金。
我个人完全不喜欢这种方法。 composer.lock 永远不应该添加到 Git 存储库中,永远不要。正确的方法是在暂存时使用 composer update 然后将文件同步到生产中(当然,如果一切正常的话)。登台必须是生产环境的精确副本。 composer.lock 应该是 .gitignore 的一部分。
composer.lock 必须包含在您的 CSV 中!!!您还如何确保每个人都使用相同的版本?所以永远不要从你的 CSV 中排除 composer.lock !!!
@TobiasGaertner我认为您的意思是VCS(版本控制软件),但否则您是正确的并且符合the project's official recommendations

L
Luciano Nascimento

为什么

恕我直言,Composer 现在默认使用 --dev 标志(在安装 更新时)是有充分理由的。 Composer 主要在需要行为的场景中运行:

Composer 的基本工作流程如下:

启动一个新项目:composer.phar install --dev,json 和 lock 文件被提交到 VCS。

其他开发人员开始从事该项目:检查 VCS 和 composer.phar install --dev。

开发人员添加依赖项:composer.phar 需要 ,如果您想要包在 require-dev 部分(并提交),请添加 --dev。

其他人继续:(结帐和)composer.phar install --dev。

开发人员想要更新版本的依赖项:composer.phar update --dev (和提交)。

其他人继续:(结帐和)composer.phar install --dev。

项目已部署:composer.phar install --no-dev

如您所见,--dev 标志的使用(远)多于 --no-dev 标志,尤其是当从事该项目的开发人员数量增加时。

生产部署

在不安装“dev”依赖项的情况下部署它的正确方法是什么?

那么,composer.jsoncomposer.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


我同意大部分所说的,但有一个例外。 “composer install --no-dev”应该只在临时环境中执行,并且该环境应该被认为是不可变的。我不想在我的生产服务器上直接下载任何依赖项,而无需通过预览/登台。这只是一个额外的小心。
@Scalable:虽然我同意你的观点(斯文在他的回答中很好地涵盖了这一点),但这不是我回答的范围,也不是我所说的“生产部署”。我添加了一段来说明这一点。
其实我认为默认应该是不太危险的选项。将 --dev 设为默认值并在生产环境中意外安装 composer 可能是致命的。
--optimize-autoloader 中的好点。还请考虑 --classmap-authoritative - 从此处的文档 getcomposer.org/doc/03-cli.md 您可以看到:“仅从类映射中自动加载类。隐式启用 --optimize-autoloader”,因此如果您知道类“存在”,则可以使用,这可能除非您动态生成类,否则应该在您的 prod 环境中发生。
很好的答案,我建议直接在 composer.json 中添加 optimize-autoloader{"config": { "optimize-autoloader": true } }
C
Community

实际上,我强烈建议不要在生产服务器上安装依赖项。

我的建议是检查部署机器上的代码,根据需要安装依赖项(这包括如果代码投入生产,则不安装开发依赖项),然后将所有文件移动到目标机器。

为什么?

在共享主机上,您可能无法访问命令行

即使你这样做了,PHP 可能会在命令、内存或网络访问方面受到限制

可能不会安装存储库 CLI 工具(Git、Svn),如果您的锁定文件记录了检查某个提交而不是将该提交作为 ZIP 下载(您使用 --prefer-source 或 Composer 有没有其他方法可以获得该版本)

如果您的生产机器更像是一个小型测试服务器(想想 Amazon EC2 微型实例),则可能甚至没有足够的内存来执行 composer install

尽管作曲家试图不破坏任何东西,但您对以部分损坏的生产网站结束感觉如何,因为在作曲家安装阶段无法加载一些随机依赖项

长话短说:在您可以控制的环境中使用 Composer。您的开发机器确实符合条件,因为您已经拥有操作 Composer 所需的所有东西。

在不安装 -dev 依赖项的情况下部署它的正确方法是什么?

使用的命令是

composer install --no-dev

这将适用于任何环境,无论是生产服务器本身,还是部署机器,或者是应该进行最后检查的开发机器,以发现是否有任何开发需求被错误地用于真实软件。

该命令不会安装或主动卸载 composer.lock 文件中声明的开发要求。

如果您不介意在生产服务器上部署开发软件组件,则运行 composer install 可以完成相同的工作,但只会增加移动的字节数,并且还会创建更大的自动加载器声明。


有趣的工作流程,但有一个很大的缺点:存储库不应该包含供应商文件夹/内容本身(Composer 页面上的官方声明),因此它们永远不会在基于 git 的部署中直接推送到生产环境(这是一个常见的标准 afaik,如我错了请纠正我)。所以基本上上述解决方案只适用于“老式” FTP 部署!?请让我们进一步讨论这个...
我建议的工作流程不包括通过 GIT 将代码推送到生产服务器。事实上,我建议不要这样做,因为这样做会迫使您在生产服务器上安装 Composer 依赖项,这可能会带来很多问题。如果您希望您的部署顺利运行,您必须在销毁当前版本并替换它之前组装运行应用程序所需的所有代码。不喜欢 FTP?通过 SSH 进行 RSync,然后通过翻转符号链接来切换版本。但如果你愿意,你也可以在 prod 中 push、checkout 和 composer install。
@Panique:我刚刚看到你评论的那一部分,我必须回答:“在基于 git 的部署中推送到生产环境(这是一个常见的标准 afaik,如果我错了,请纠正我)” - 不,这个不是通用标准。这只是一种方法。
我所在的团队已将其纳入他们的工作流程并取得了巨大成功。我们有一台构建机器(当然是 Jenkins),它:1)从 SC 签出 2)运行 composer install/update 3)运行单元测试 4)删除开发依赖项 5)生成一个 phar 文件(app-1.34.phar 等)。有一个单独的机制被通知并决定何时获取该文件,将其传输到何处以及如何处理它。一些团队选择将 phar 放在服务器上后对其进行解包,而一些团队则按原样运行它。它为我们部署的稳定性和可重复性提供了很大的信心。
我100%同意这个答案。 Composer 不应该安装在部署服务器上,也不应该安装在 git 上。持续部署/集成服务器应该管理源代码和依赖项获取:git pull > composer install > deploy
d
dave1010

现在默认启用 require-dev,对于本地开发,您可以在没有 --dev 选项的情况下执行 composer installcomposer 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/toolprod/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。
d
datashaman

我认为最好使过程自动化:

在您的 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 而不验证它没有破坏任何东西。
@Sven 这是在同一评论中建议在部署之前自动运行单元测试的方式。但你是对的,最好还是保留 composer.lock 文件。
现在您唯一需要解释的是:如何在没有 PHPUnit 等开发依赖项的情况下在服务器上运行测试?
如果将依赖项、测试和部署放在一个工具中,例如 Java Gradle 或 SBT 甚至 Maven(maven 不太好),那就太好了。一个使 composer phpunit 和部署协同工作的 PHP 工具。甚至是制作这些东西的 Gradle 或 Scala SBT 插件,因为它们是不可知的构建工具,该插件甚至可以使用资产,如最小化 javascript 和编译 sass,最小化 css。有人知道吗?
当然这是在服务器中测试真实环境,而不是直接在站点 vhost 中完成,您可以将其放在一个单独的临时文件夹中,并在成功时将结果移动到 vhost
A
Abhi Beckert

在生产服务器上,我将 vendor 重命名为 vendor-<datetime>,并且在部署期间将有两个供应商目录。

HTTP cookie 导致我的系统选择新的供应商 autoload.php,在测试之后,我在它们之间进行了完全原子/即时切换,以禁用旧的供应商目录以处理所有未来的请求,然后在几天后删除以前的目录。

这避免了我在 apache/php 中使用的文件系统缓存引起的任何问题,并且还允许任何活动的 PHP 代码继续使用以前的供应商目录。

尽管有其他建议反对它,但我个人在服务器上运行 composer install,因为这比我的暂存区域(我的笔记本电脑上的 VM)的 rsync 更快。

我使用 --no-dev --no-scripts --optimize-autoloader。您应该阅读每个文档以检查这是否适合您的环境。