Blog image 10 tricks to work efficiently with the Composer in Drupal 8

10 tricks to work efficiently with the Composer in Drupal 8

19.04.2019

These days, Composer is one of the most important tools in the PHP world, since it enables developers to deal with managing external libraries while facilitating their ongoing updates. If you can’t imagine working efficiently with Drupal 8 without using Composer, read the following 10 tips to help you better understand and tap the power of the popular package manager.

1. Update both the modules and the core with Composer

Drupal 8 and Composer can work together, but the conditions for said cooperation are quite specific, particularly when it comes to core updates. The latest Drupal 8 release package downloaded from the official website is configured in such a way that Composer can download only modules, themes and external libraries. The core itself needs to be updated manually.

Having to update things manually makes using a package manager moot, but there’s a simple way to fix that. You can use the template found at https://github.com/drupal-
composer/drupal-project
. I cannot recommend this way of launching new projects in Drupal enough – here at Droptica, we use it for the vast majority of our projects. It allows you to store only your own code in the repository, with no external dependencies. When a new version of Drupal is released, just download it by running:

composer update drupal/core --with-all-dependencies

2. Speed things up with hirak/prestissimo

Composer is hardly famous for its speed or resource efficiency. One of the reasons for this is the sequential nature of the install command. Subsequent libraries are downloaded one after the other and in case of any downtime, the installation won’t move at all and will only extend.

To overcome this limitation, enable the Prestissimo plugin (https://github.com/hirak/prestissimo). It enables Composer to do parallel downloads. Thanks to this plugin, even the most complex project will be installed even several times faster than before.

composer global require hirak/prestissimo

What are the potential drawbacks of Prestissimo? First and foremost, there may be some issues with private repositories (you have to define the necessary tokens and keys in the auth.json file), and second – starting with version 2.0 of the Composer, the plugin will become redundant – it will be replaced by curl-multi support.

3. Reduce Composer’s hunger for memory with Drupal Optimizations

In the previous tip, I mentioned composer’s... love for RAM. In the case of Drupal 8, this phenomenon is further exacerbated by a multitude of external dependencies, especially Symfony ones. This issue has already been noticed by the Symfony and Drupal communities. The solution in the form of a Composer plugin was devised and developed by Jakub Piasecki, a Polish developer. It has been a part of the popular template (https://github.com/drupal-composer/drupal-project) for quite some time now.

In order to add Drupal Optimizations to your project, run:

composer require zaporylie/composer-drupal-optimizations:^1.1

How does the plugin work? It assumes that you are using Drupal version >= 8.5. Based on this assumption, it avoids checking older tags in Symfony component repositories. Optimising Composer using this method reduces its memory consumption to less than a third, at least according to the plugin’s author. This makes the composer update command run much faster.

4. Control the available memory limit

If the two aforementioned plugins are not enough and you still run into problems with exceeding the memory limit, the only way to alleviate the issue might be making it higher. The official documentation provides a number of ways to do so. Composer tries to increase the limit to 1.5 GB each time it starts up, but even that is often not enough.

If you run into Composer not reacting to changing the limit value, make sure that you edit the correct configuration file – first and foremost check, if it is included in the list shown after running the php --ini command. You should also make sure that the server you are running Composer on allows for such a high memory consumption. If you have problems with composer update, keep in mind that you can run it locally with a higher limit and generate composer.lock file, then use it to run composer install command on the server – it will definitely use much fewer resources.

5. Discover the outdated command and the --dry-run option

Most Composer users use mainly install and update commands. There's nothing wrong with that… That is until you need more control over the update process. If you want to find out what composer update command is going to do, run it with the --dry-run option. As the name suggests, it will then run “dry”, without introducing any changes to the code.

Another way to view the available updates is to run the composer outdated command. It provides a clear overview of all packages that need to be updated (a separate colour is used for packages with newer versions that are blocked by restrictions implemented in composer.json). This is a great alternative to the Update Manager module.

6. Convert your project using Composerize

If you already have a Drupal 8 project that is not maintained using Composer, fear not! You can use several tools which can generate a composer.json file based on the code found in a given project. The most commonly used plugin? That would be grasmash/composerize-drupal. You can install it by running:

composer global require grasmash/composerize-drupal

After running the following commands (assuming that [repo-root] is the path to the project’s root directory, and [drupal-root] is the path to index.php), you will get a composer.json file containing all the modules, themes and profiles in the project, configured to handle patching and downloading packages from https://asset-packagist.org/.

cd path/to/drupal/project/repo
composer composerize-drupal --composer-root=[repo-root] --drupal-root=[drupal-root]

Running composer install will install the latest versions of the modules and will replace the current ones. From that point on, external dependencies will no longer have to be stored in the project repository – just place the composer.json and composer.lock files in there.

7. Learn more about Asset Packagist

Composer is mainly used to manage PHP packages; however, it can also work with NPM and Bower repositories. This is particularly useful if you want to maintain the latest versions of frontend libraries (such as Colorbox or Slick). This is enabled by the Asset Packagist project (https://asset-packagist.org/).

In order to be able to use additional libraries, define a new repository in composer.json:

"repositories": [
    {
        "type": "composer",
        "url": "https://asset-packagist.org"
    }
]

Keep in mind to change the location of libraries to one that is compatible with Drupal. In order to do so, make sure that your project includes the composer/installers add-on:

composer require composer/installers

Then add the following entries in the "extras" section of composer.json:

"extra": {
    "installer-types": ["bower-asset", "npm-asset"],
    "installer-paths": {
      "web/libraries/{$name}": ["type:bower-asset", "type:npm-asset"]
    }
}

Let’s assume you want to add Colorbox to your website. First, you need to find it at https://asset-packagist.org/, then click on its title and wait for Asset Packagist to download information about Colorbox to its repository (this step is not always necessary, it may be needed for less-popular libraries).

Copy the full name of the package with the npm-asset/bower-asset prefix and run:

composer require npm-asset/jquery-colorbox

If all goes well, Colorbox will be added to your project's web/libraries directory.

One important thing about Asset Packagist – I need to point out that using it makes sense only if you need to download a single library to the project without any additional
dependencies, in the exact shape and form found in the repository. Composer will not be able to replace npm install colorbox, which in addition to Colorbox downloads and installs anywhere from several dozen to several hundred dependencies. This approach has some pros and cons. One of the major advantages is saving space and avoiding downloading unnecessary files, and one of the biggest drawbacks is the inability to run code derived from NodeJS. In other words, you will have an easier time updating frontend libraries, but you pay for it by losing the ability to compile them yourself.

8. Don't be afraid to use Cweagan's Patches

Using .patch files is common in Drupal and has an extremely long history. Composer makes it easy to manage patches and control their advanced sets. Let’s start with a command adding Cweagan's Patches plugin to the project:

composer require cweagans/composer-patches

Add the necessary configuration in composer.json:

"patches": {
    "drupal/core": {
        "Fix everything": "patches/core_fix_everything.patch",
        "Fix one more thing": "https://www.drupal.org/files/issues/fix-one-more.patch"
    },
    "drupal/colorbox": {
        "Fix something": "patches/colorbox_fix_something.patch",
    }
}

Patch files can be located both in your repository, as well as somewhere online. You can find more configuration options in the documentation at https://github.com/cweagans/composer-patches. All patches from the above list will be automatically applied to the original files the next time you run composer update.

What are the benefits of using Cweagan's Patches? First and foremost, you will now have all the patches in one place, and you will be able to forget about applying them manually – Composer will take care of it. However, you still have to make sure that the changes contained in the patches are not already included in newer versions of the updated packages.

9. A bit of paranoia never killed a Drupal developer

Drupal is a security-oriented project, but at the same time, its architecture might be a source of some potential risks. This primarily concerns the directory structure, which forces you to put too many files with PHP code in the webroot – the directory that is accessible from the outside. Despite the fact that proper configuration eliminates the possibility of reading this code, modern practices – promoted mainly by Symfony – aim at leaving files intended for the end user in webroot.

Integrating Drupal with Composer has opened new possibilities to protect PHP files against accidental access. Theoretically, all paths of downloaded libraries can be freely changed, as autoload takes care of finding them. The extreme case of using this Composer feature is the https://github.com/drupal-composer/drupal-paranoia template. It forces all project files to be stored in a separate /app directory, making only symlinks to resources such as index.php or sites/*/files directories available to the outside world.

Of course, using this approach requires running a *nix system.

10. Optimise your production version

There are some basic rules regarding using Composer in a production environment. Adhering to them will increase the security of your website and speed it up:

  • Use only the composer install command in the production environment and make sure that composer.lock is always in the repository. If you allow composer update to run, you might run into some unforeseen consequences. You should always do updates in a development environment – This approach will allow you to avoid problems with incompatibilities of new versions.
  • Use the composer install --no-dev option to stop development libraries from installing. These are declared in the require-dev section of composer.json.
  • Use the composer install --optimize-autoloader option to build a class map. Thanks to this, the autoloader will not search for files on disk according to PSR-4/PSR-0 rules, instead, it will get a path to a file with its definition based on the class name. Activating this optimisation in the development environment is troublesome, as it requires cleaning the cache after each change in the project file structure.

Looking for web development experts?
Check our services

All services
Drupal
Symfony
React
PHP
DevOps
Nodejs
Design/UX