Adding non-PHP dependencies to a Composer-based project

Over the past few years, the Drupal community has been (sometimes slowly) embracing the Composer dependency manager tool for PHP projects. We have become accustomed to adding Drupal modules and base themes to our projects using composer require but many of us have only scratched the surface of what more Composer can do for us.

In this article, we'll go step-by-step in adding a non-PHP dependency to our project using Composer - as well as the helpful Composer installers extender plugin. We'll utilize Asset Packagist, a Composer repository for many popular NPM and Bower assets including things like Javascript libraries and CSS frameworks.

The general idea is that for just about any Drupal module or base theme that asks you to manually download an external library - you can use this method instead of manual steps.

Example 1: Simple, but not super-useful

Let's start with a simple example - adding the required Photoswipe module's library. The instructions for this module include some manual steps to download and place the plugin in a specific directory as well as an alternative installation using Composer. In this example, we'll accomplish the download part using Asset Packagist.

First, add the Photoswipe Drupal module using:

composer require drupal/photoswipe

Next, add Asset Packagist to the repositories section of the project's composer.json file:

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

Then, find the Photoswipe Javascript library on Asset Packagist.

Finally, require the Photoswipe Javascript library using:

composer require npm-asset/photoswipe

Supereasy, right?! Yes, but notice that the Photoswipe library wasn't installed in the proper /web/libraries/ location. Instead, Composer installed it in its default location for dependencies, the /vendor/ directory. Because the Photoswipe library doesn't have a composer.json file, and therefore doesn't have a Composer "type", there's nothing that the Composer installers plugin can do to help.

Example 2: Placement

The Composer installers extender plugin can help with this task. It allows us to extend the types of dependencies that Composer installers can handle (by default, Composer installers only handles a specific set of dependency types. First, add the Composer installers extender plugin to your project:

composer require oomphinc/composer-installers-extender

Let's back up example 1 a bit so we can not only download the Photoswipe library to our project, but also put it in the proper place.

composer remove npm-asset/photoswipe

Next, we need to let Composer installers extender that we want its help in handling Composer dependencies from the npm-asset vendor. We do this by adding a bit of configuration to our project composer.json's extras section:

"installer-types": ["npm-asset"],

This allows Composer installers extender to help Composer installers place dependencies from the npm-asset vendor in a custom directory. Let's set the custom directory by adding to the default (if you're using the drupal/recommended-project Composer template) installer-paths section of the composer.json file:

"web/libraries/{$name}": [
  "type:drupal-library",
  "npm-asset/photoswipe"
],

Finally, use Composer to re-require the Photoswipe library:

composer require npm-asset/photoswipe

Verify that the Photoswipe Javascript library has been installed in the web/libraries/ directory. 

Summary

The combination of Asset Packagist and the Composer installers extender really opens the door to allow you to manage the vast majority of all your project dependencies in a consistent manner. 

Use it to install Bootstrap, Foundation, the Chosen module's Javascript library, A11y, Babel, and other popular NPM and Bower packages. 

Comments