当使用composer的开发/生产开关时,如何正确部署?

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

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

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

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

composer install --dev

问题,问题:

Composer在2013年极大地改变了installupdate的行为,require-dev-dependencies现在默认安装(!),请随意创建一个Composer。require-dev块,并执行composer install来重现。

最受欢迎的部署方式是推动编曲者。(保存您当前的作曲器设置),然后在生产服务器上执行composer install,这也将安装开发的东西。

部署这个没有安装-dev依赖项的正确方法是什么?

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

197266 次浏览

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

我的建议是在部署机器上签出代码,根据需要安装依赖项(如果代码用于生产,则不安装开发依赖项),然后将所有文件移动到目标机器上。

为什么?

  • 在共享主机上,您可能无法访问命令行
  • 即使你这样做了,PHP也可能在命令、内存或网络访问方面受到限制
  • 存储库CLI工具(Git, Svn)可能没有安装,如果你的锁文件记录了一个依赖项来检出某个提交,而不是以ZIP格式下载该提交(你使用——prefer-source,或者Composer没有其他方法来获得该版本),这将失败。
  • 如果你的生产机器更像是一个小型测试服务器(想想Amazon EC2微实例),那么可能甚至没有足够的内存安装来执行composer install
  • 虽然作曲家试图不破坏东西,你如何看待以部分破坏的生产网站结束,因为一些随机的依赖无法在作曲家安装阶段加载

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

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

要使用的命令是

composer install --no-dev

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

该命令不会安装或主动卸载编写器中声明的开发需求。锁文件。

如果你不介意在生产服务器上部署开发软件组件,运行composer install将完成同样的工作,但只是增加了移动的字节量,并创建了一个更大的自动加载器声明。

现在,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默认使用--dev标志(在安装而且更新时)有一个很好的理由。Composer主要在需要这种行为的场景中运行:

Composer的基本工作流程如下:

  • 一个新的项目开始了:composer.phar install --dev, json和锁文件被提交给VCS。
  • 其他开发人员开始处理这个项目:签出VCS和composer.phar install --dev
  • 开发人员添加依赖项:composer.phar require <package>,如果你想在require-dev部分中添加包(并提交),则添加--dev
  • 其他的跟随:(checkout和)composer.phar install --dev
  • 开发人员想要更新版本的依赖项:composer.phar update --dev <package>(和commit)。
  • 其他的跟随:(checkout和)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文件可能包含有关dev-packages的信息。这无关紧要。--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。更多信息在这里

我认为最好是自动化这个过程:

添加作曲家。锁文件在你的git存储库中,确保你在发布时使用作曲家。Phar安装—无需开发,但在你的开发机器中,你可以使用任何composer命令而不用担心,这不会进入生产,生产将基于锁文件的依赖关系。

在服务器上签出此特定版本或标签,并在替换应用程序之前运行所有测试,如果测试通过,则继续部署。

如果测试依赖于开发依赖项,因为编写器没有测试范围依赖项,一个不太优雅的解决方案可以使用开发依赖项(作曲家。phar安装)运行测试,删除供应商库,再次运行作曲家。Phar安装—无需开发,这将使用缓存的依赖项,因此更快。但如果你知道其他构建工具中作用域的概念,这就是一种hack

自动化这些,忘记其他的,去喝杯啤酒吧。

PS:正如下面的@Sven评论,不签出作曲家不是一个好主意。锁定文件,因为这将使编写器安装工作作为编写器更新。

你可以用http://deployer.org/来实现自动化,这是一个简单的工具。

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

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

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


尽管其他答案建议反对它,但我个人在服务器上运行composer install,因为这比从我的临时区域(笔记本电脑上的虚拟机)进行rsync更快。

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