Goodbye Drush Make, Hello Composer!

by Karen Stevenson

I’ve built and rebuilt many demo Drupal 8 sites while trying out new D8 modules and themes and experimenting with new functionality like migrations. After installing D8 manually from scratch so many times, I decided to sit down and figure out how to build a Drupal site using Composer to make it easier. The process is actually very handy, sort of the way we’ve used Drush Make in the past, where you don’t actually store all the core and contributed module code in your repository, you just record which modules and versions you’re using and pull them in dynamically.

I was a little worried about changing the process I’ve used for a long time, but my worries were for nothing. Anyone who’s used to Drush would probably find it pretty easy to get this up and running. 

TLDR: How to go from an empty directory to a fully functional Drupal site in two command lines:

sudo composer create-project drupal-composer/drupal-project:~8.0 drupal --stability dev --no-interaction

cd drupal/web
../vendor/bin/drush site-install --db-url=mysql://{username}:{password}@localhost/{database}

Install Composer

Let's talk through the whole process, step by step. The first step is to install Composer on your local system. See https://getcomposer.org/download/ for more information about installing Composer.

Set Up A Project With Composer

To create a new Drupal project using Composer, type the following on the command line, where /var/drupal is the desired code location:

cd /var
sudo composer create-project drupal-composer/drupal-project:~8.0 drupal --stability dev --no-interaction

The packaging process downloads all the core modules, Devel, Drush and Drush Console, and then moves all the Drupal code into a ‘web’ subdirectory. It also moves the vendor directory outside of the web root. The new file structure will look like this:

File directory structure

You will end up with a composer.json file at the base of the project that might look like the following. You can see the beginning of the module list in the ‘require’ section, and that Drush and Drupal Console are included by default. You can also see rules that move contributed modules into ‘/contrib’ subfolders as they’re downloaded.

{
    "name": "drupal-composer/drupal-project",
    "description": "Project template for Drupal 8 projects with composer",
    "type": "project",
    "license": "GPL-2.0+",
    "authors": [
        {
            "name": "",
            "role": ""
        }
    ],
    "repositories": [
        {
            "type": "composer",
            "url": "https://packagist.drupal-composer.org"
        }
    ],
    "require": {
        "composer/installers": "^1.0.20",
        "drupal/core": "8.0.*",
        "drush/drush": "8.*",
        "drupal/console": "~0.8",
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "post-install-cmd": "scripts/composer/post-install.sh"
    },
    "extra": {
        "installer-paths": {
            "web/core": ["type:drupal-core"],
            "web/modules/contrib/{$name}": ["type:drupal-module"],
            "web/profiles/contrib/{$name}": ["type:drupal-profile"],
            "web/themes/contrib/{$name}": ["type:drupal-theme"],
            "web/drush/commands/{$name}": ["type:drupal-drush"]
        }
    }
}

That site organization comes from https://github.com/drupal-composer/drupal-project/tree/8.x. A README.md file there describes the process for doing things like updating core. The contributed modules are coming from Packagist rather than directly from Drupal.org. That’s because the current Drupal versioning system doesn’t qualify as the semantic versioning the system needs. There is an ongoing discussion https://www.drupal.org/node/1612910 about how to fix that.

Install Drupal

The right version of Drush for Drupal 8 comes built into this package. If you have an empty database you can then install Drupal using the Drush version in the package:

cd drupal/web
../vendor/bin/drush site-install --db-url=mysql://{username}:{password}@localhost/{database}

If you don’t do the installation with Drush you can do it manually, but the Drush installation handles all this for you. The manual process for installing Drupal 8 is:

  • Copy default.settings.php to settings.php and unprotect it
  • Copy default.license.yml to license.yml and unprotect it
  • Create sites/files and unprotect it
  • Navigate to EXAMPLE.COM/install to provide the database credentials and follow the instructions.

Add Contributed Modules From Packagist

Adding contributed modules is done a little differently. Instead of adding modules using drush dl, add additional modules by running composer commands from the project root (one level above the Drupal root):

composer require drupal/migrate_upgrade 8.1.*@dev
composer require drupal/migrate_plus 8.1.*@dev

As you go, each module will be downloaded from Packagist and composer.json will be updated to add this module to the module list. You can peek into the composer.json file at the root of the project and see the ‘require’ list evolving.

Repeat until all desired contributed modules have been added. The composer.json file will then become the equivalent of a Drush make file, with documentation of all your modules.

For even more parity with Drush Make, you can add external libraries to your composer.json as well, and, with a plugin, you can also add patches to it. See more details about all these options at https://www.drupal.org/node/2471553.

Commit Files to the Repo

Commit the composer.json changes to the repo. The files downloaded by Composer do not need to be added to the repo. You’ll see a .gitignore file that keeps them out (this was added as a part of the composer packaging). Only composer.json, .gitignore, code in /web/modules/custom and the content of the /web/sites subdirectory (other than the files directory) will be stored in the git repository.

.gitignore

# Ignore directories generated by Composer
vendor
web/core
web/modules/contrib
web/themes/contrib
web/profiles/contrib

# Ignore Drupal's file directory
web/sites/default/files

Update Files

To update the files any time they might have changed, navigate to the Drupal root on the command line and run:

composer update

Add additional Drupal contributed modules, libraries, and themes at any time from the project root with the same command used earlier:

composer require drupal/module_name 8.1.*@dev

That will add another line to the composer.json file for the new module. Then the change to composer.json needs to be committed and pushed to the repository. Other installations will pick this change up the next time they do git pull, and they will get the new module when they run composer update.

The composer update command should be run after any git pull or git fetch. So the standard routine for updating a repository might be:

git pull
composer update
drush updb
...

New Checkout

The process for a new checkout of this repository on another machine would simply be to clone the repository, then cd into it and run the following, which will then download all the required modules, files, and libraries:

composer install

Odds and Ends and Errors

Since I wrote this article several people have run into odd problems that I didn't have, so here are some things to investigate if you have problems with this:

  • Depending on your local setup, you may need to prefix all your Composer commands with sudo, to avoid permission errors when Composer tries to update files.
  • If you get everything working from Drush but you can't access the site from the browser, you may have run into this problem. The solution is to change ../vendor/bin/drush site-install --db-url=mysql://{username}:{password}@localhost/{database} to ../vendor/bin/drush site-install --db-url=mysql://{username}:{password}@127.0.0.1/{database}.

That’s It

So that’s it. I was a little daunted at first but it turns out to be pretty easy to manage.  You can use the same process on a Drupal 7 site, with a few slight modifications.

newsletter-bot