How to deploy correctly when using Composer's develop / production switch?
Why
There is IMHO a good reason why Composer will use the --dev
flag by default (on install and update) nowadays. Composer is mostly run in scenario's where this is desired behavior:
The basic Composer workflow is as follows:
- A new project is started:
composer.phar install --dev
, json and lock files are commited to VCS. - Other developers start working on the project: checkout of VCS and
composer.phar install --dev
. - A developer adds dependancies:
composer.phar require <package>
, add--dev
if you want the package in therequire-dev
section (and commit). - Others go along: (checkout and)
composer.phar install --dev
. - A developer wants newer versions of dependencies:
composer.phar update --dev <package>
(and commit). - Others go along: (checkout and)
composer.phar install --dev
. - Project is deployed:
composer.phar install --no-dev
As you can see the --dev
flag is used (far) more than the --no-dev
flag, especially when the number of developers working on the project grows.
Production deploy
What's the correct way to deploy this without installing the "dev" dependencies?
Well, the composer.json
and composer.lock
file should be committed to VCS. Don't omit composer.lock
because it contains important information on package-versions that should be used.
When performing a production deploy, you can pass the --no-dev
flag to Composer:
composer.phar install --no-dev
The composer.lock
file might contain information about dev-packages. This doesn't matter. The --no-dev
flag will make sure those dev-packages are not installed.
When I say "production deploy", I mean a deploy that's aimed at being used in production. I'm not arguing whether a composer.phar install
should be done on a production server, or on a staging server where things can be reviewed. That is not the scope of this answer. I'm merely pointing out how to composer.phar install
without installing "dev" dependencies.
Offtopic
The --optimize-autoloader
flag might also be desirable on production (it generates a class-map which will speed up autoloading in your application):
composer.phar install --no-dev --optimize-autoloader
Or when automated deployment is done:
composer.phar install --no-ansi --no-dev --no-interaction --no-plugins --no-progress --no-scripts --optimize-autoloader
If your codebase supports it, you could swap out --optimize-autoloader
for --classmap-authoritative
. More info here
Best practice to deploy release on production
I suggests to use this approach to achieve almost zero down time:
The root directory of the web server must be just a symbolic link.
- Create a new directory for every release and upload the files into it.
- Install your dependencies.
- Run your tests.
- Create a symbolic link as the root directory of the web server that points to the new release directory.
So you don't have to shutdown your website for coping and uploading files directly to the root directory. Just use symbolic links. Also in this way it is much easier to rollback to any old release.
Do I need composer on TYPO3 production-system when my TYPO3 is in composer mode
As you have correctly discovered you don't need Composer once all packages have been installed and autoload info has been dumped.
If you do all this locally or on a CI server and then upload all files, e.g. with rsync
then you have a running compilation of your instance. There are no changes to packages or autoload info at runtime which could require Composer.
Avoid installing composer's require-dev libraries in production
Aha... I missed the --no-dev
flag previously. Apparently you have to specifically tell composer install
that it should ignore the require-dev
sections. In a way this makes sense, since you more often type composer install
on your development laptop, and composer install --no-dev
will probably be a part of a deployment script where you don't need to think about it. So the defaults are set up for developer convenience.
Related Topics
How to Use Perl Libraries from PHP
Mysqli - Fetch_Array Error Call to a Member Function Fetch_Array() on a Non-Object MySQLi
How Does SQL-Injection Work and How to Protect Against It
Why Is My Number Value Changing Using Number_Format()
PHP - Add Two Hours to Date Variable
When and Where Should I Use Session_Start
Distance Calculations in MySQL Queries
Checking If 2 Arrays Have at Least 1 Equal Value
How to Fix 'Creating Default Object from Empty Value' Warning in PHP
How to Bind Decimal/Double/Float Values with Pdo in PHP
How to Convert PHP Regex to JavaScript Regex
Change Innerhtml of a PHP Domelement
Get Number of Rows Matched by Update Query with PHP MySQLi
Explode a Paragraph into Sentences in PHP