I'm not intended to push until I get that new Composerizing verb to be into the dictionary, but I wan't to leave track of my experience about how to implement Composer on our old Drupal projects where it wasn't used before, and why move to this new work schema so maybe some developers who were habituated to work with older versions of Drupal, and I'm talking about Drupal 7 and early versions of 8, can find here a useful reference to guide them through their way to truth and happiness. (!)
—"But why Composer?"—, asked the dinousaur
It might look a very antiquated question for those who came to Drupal recently or people who already work with PHP frameworks like Laravel, but let's talk a little about the old school: these old good times when we wanted to create a new Drupal 6 or 7 based website and we went straight to Drupal.org and downloaded the tarball file, we created a database and simply ran the install script; if we wanted to install a module we only had to upload it to our site via FTP to the sites/all/modules and enabled it in the admin interface and we were done. Then came Drush into play and we learnt the possibility of doing that faster by typing a simple command on the console aside another maintenance tasks like module updates, cache rebuilding and so on.
After a long wait we had available Drupal 8 and its Symfony-based core which gave it enough superpowers to behave not just like a CMS but like a whole framework, the rules began to change. Anyway we kept the chance to build and manage websites with no difficulties; in the worst case we could update the Drupal core by deleting the core and vendor files just as indicated in the README file and that was enough.
Here started to arise the first symptoms of discomfort and we started to suspect we had to do the job in a different way because the update task became unpleasant and slower (because the core was a lot heavier than prior versions). Well, maybe Drush could handle it so we could avoid some headaches for a long time until it came Drush 9, now deprecating its well old known abilities to download modules and update websites; the kid said it's no longer its duty and Composer should be doing the homework so you could think it's like a dead-end already.
There's one reason for that, so let's be cool and try to understand why all of this did it happen. The software is becoming more complex as the time goes by and there are new versions of PHP, some of the libraries are being updated and some others went rot on in oblivion, some of them depend on others and the possibility of your site stops working because you don't have the right version of any of these components grows insanely. Another thing to keep in mind is how workflows are evolving: collaborative Git repositories are now a must so the management of different development environments. Here's where Composer comes to the rescue and it helps us to solve this madness path in a great way.
Yeah, the world of Composer is not beautiful and wonderful but it's definitely better than struggling with all this chaos by yourself. Let's imagine a simple scenario where you have installed the A module in your site which relies on the X 1.0 library, but now you need the B module too and it requires the 1.5 version of X which is incompatible with its predecessor. Composer does just that: it's a dependency management system entitled to download the most appropriate version of dependencies for our project. The setup process of Composer is very simple and you can find the instructions on its official website.
The Composer's Drupal project and module management
Composer has the ability to create new projects based on frameworks such as Symfony, Laravel or Drupal. We are interested now on the Drupal project and we only need to run the following command in our console:
composer create-project drupal-composer/drupal-project:8.x-dev my_site_name_dir --stability dev --no-interaction
This will give us a boilerplate codebase to start a new Drupal project from scratch. This new project will contain a composer.json file with the appropriate settings ready to be handled by Composer.
In addition to the default Composer repository where it downloads the PHP dependencies needed by our project, this composer.json file will have the right URL of the Drupal repository where modules and themes can be downloaded just like another dependency. For instance let's think we would want to install the Pathauto module, so we would only need to run this command from our Drupal site directory:
composer require drupal/pathauto
And Composer will download the most adequate version for our site, something like that old drush dl command we used in the past. The core and module updates can be handled with the composer update command too. We could also tell Composer to download certain modules exclusively in our dev environments and avoid the production ones.
Another thing to think about: core and vendor exclusion
When we talk about working beside a developers team it becomes handy the use of Git repositories. If we look at the example.gitignore file included in Drupal core, we are suggested to exclude the core and vendor folders where Drupal core and Symfony libraries are stored. This is because as we said before, there might be some conflicts between different versions of dependencies.
Also our projects will become a lot heavier and harder to support if we don't dismiss these folders in our repository. I found a lot of problems within my experimental process as some libraries inside vendor use to manage its own sub-repositories and that turns out into conflict when committing changes to your main repository. Does it look like fun? Well, we might better exclude these two folders for the good.
Okay, so now let's talk about composerization
At this point everything sounds sweet, right? But what about our older Drupal 8 websites if these were not created by the Composer Drupal project and they don't have neither the appropriate composer.json and file structure to be handled with the dependencies manager? Surely these projects already has a composer.json file on its root but it will lack of the required elements to manage Drupal modules as dependencies:
- The Drupal repository where modules and themes can be found.
- Path settings where Composer is told to download these dependencies.
We can help ourselves by this simple Composer plugin called composerize-drupal which can be installed with the following command:
composer global require grasmash/composerize-drupal
Of course you should be trying this on a test environment first and backing up your site before: be warned.
You should run this plugin inside a working copy of your website; if you just downloaded your Drupal site from a repository which already excluded the core and vendor folder expecting these to be downloaded once composerized, it won't work. On the other hand, once you ran the plugin you can exclude these folders in your .gitignore file and you can continue committing to your repository.
If you are at the root folder of your site, the following command should do the work of composerization:
composer composerize-drupal --composer-root=. --drupal-root=.
Pretty simple though I would recommend to check out the entire documentation of this marvelous plugin at its Github repository.
I also advice you to take your time and read this great article which I found precisely after working with the composerize-drupal plugin: Drupal 8 Composer Best Practices.