Speeding up Composer inside a Vagrant box

There has been a lot written about how to speed up Symfony when running it inside a Vagrant box. In my opinion, the most interesting one is Running the Symfony application on Vagrant without NFS below 100ms. The change that has the biggest possitive impact on performance consists on moving the vendors/ directory outside the shared folder.

However, most of the provided solutions involve modifying your composer.json file or even the front controller code to load vendors from a different directory. You will end with something like this:

// composer.json
{
  ...
  "config": {
    "vendor-dir": "/another/path/on/fs/vendor"
  },
  ...
}

And your PHP code will look like this:

<?php
// Application front controller
require_once '/another/path/on/fs/vendor/autoload.php';

But what if we want to deploy the same code on a different environment, such as our production systems? We might want our application directory to be self-contained.

Our approach to improve our development box performance will affect where the dependencies should be installed on production, unless we apply some modifications to our code just after deploying to change the paths.

Making the vendors path configurable without changing your code

This solution lets you keep the vendors directory outside your application directory, but defaults to the current directory.

How can this be achieved without touching a single line of code when deploying? Using environment variables!

Just leave the composer.json untouched, without a vendor-dir setting, and use the following code on your front controller:

<?php
// Application front controller
$vendor_directory = getenv('COMPOSER_VENDOR_DIR');
if ($vendor_directory === false) {
  $vendor_directory = __DIR__ . '/vendor';
}

require_once $vendor_directory . '/autoload.php';

If COMPOSER_VENDOR_DIR environment variable is not set, Composer will look for the vendor/ directory inside the application directory.

You will usually set it just on your Vagrant box, preferably using a provisioning system such as Ansible or Puppet.

Setting an environment variable on Apache is as easy as:

SetEnv COMPOSER_VENDOR_DIR "/var/myapp-vendor"

If you are using nginx+php-fpm instead, php-fpm has to be configured like this:

env[COMPOSER_VENDOR_DIR] = "/var/myapp-vendor"

Don’t forget to set COMPOSER_VENDOR_DIR also when using composer from CLI.

Example

If you want to see a working example, have a look at the following AgenDAV files: