Managing an existing Drupal 8 site via Composer
I have been updating my site with Drush since beginning of Drupal 8. This week, an update has been released (Drupal 8.3.6) so i figured this would be a good time to start managing my site with Composer to maintain any external libraries that some modules may require. Also, i've had issues trying to update Metatag 8.x-1.2 module (including 8.x-1.1) via Drupal admin UI. It kept breaking my site and i just had no idea where the problem lies. However, it seems using Composer to manage Drupal fixed it.
Before we get started, you need to have Composer and Drush installed on your server. Follow this article: Install Composer on CentOS 7 (it should generally work on any linux machine, not just CentOS). Also, install Drush as well: Install Drush
You will need at at least a VPS server with 1GB RAM and root access. If you still prefer using shared hosting, then i recommend A2Hosting because they have Drush and Composer pre-installed for you to use, unlike most other shared hosting platform which do not.
It took a bit of trail and error and i'm not sure if this method is correct but it works and i'm now managing the site dependencies using Composer.
Let's get started
Please backup your site files and DB before you proceed.
SSH to your site and navigate to your webroot directory (where your Drupal is installed). There is already a composer.json file in your installation. However, we need to let it know where to fetch Drupal 8 packages.
Run this command:
composer config repositories.drupal composer https://packages.drupal.org/8
This should add:
"drupal": {
"type": "composer",
"url": "https://packages.drupal.org/8"
}
to your Drupal composer.json file.
Now open up composer.json and remove "drupal/core": "~8.3" from replace, this line here:
"replace": {
"drupal/core": "~8.3"
},
So it should look like this:
"replace": {
},
Note: I'm not sure if it helps but it doesn't give any issues anyway. so no harm in removing it.
Delete the vendor directory and run:
composer update
Note: I don't know why but during my testing, it couldn't update Drupal core until i deleted the vendor directory. It will re-fetch all the packages for vendor directory so don't worry it. You will also notice, it installs more packages than the standard Drupal that you manually download and install. You may need to run composer update again to make it gets the newer Drupal core.
At this point, it should fetch all the vendor packages including Drupal core updates if there is a newer core version. In my case, there was a new update - so it updated my existing site 8.3.5 to 8.3.6 version.
If for some reason, it hasn't managed to fetch any new Drupal core update, try running this command:
composer update drupal/core --with-dependencies
Here is a list of packages added by Composer:
duvien@local [~/public_html]# composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing composer/installers (v1.3.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing wikimedia/composer-merge-plugin (v1.4.1)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing zendframework/zend-stdlib (3.1.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing zendframework/zend-escaper (2.5.2)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing zendframework/zend-feed (2.8.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing psr/http-message (1.0.1)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing zendframework/zend-diactoros (1.4.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing twig/twig (v1.34.4)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/polyfill-mbstring (v1.4.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/translation (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing ircmaxell/password-compat (v1.0.4)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/polyfill-php55 (v1.4.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/polyfill-php54 (v1.4.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/http-foundation (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/psr-http-message-bridge (v1.0.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/polyfill-iconv (v1.4.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/event-dispatcher (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing psr/log (1.0.2)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/debug (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/http-kernel (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/routing (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony-cmf/routing (1.4.1)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing stack/builder (v1.0.4)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing paragonie/random_compat (v2.0.10)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing masterminds/html5 (2.2.2)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing guzzlehttp/psr7 (1.4.2)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing guzzlehttp/promises (v1.3.1)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing guzzlehttp/guzzle (6.3.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing doctrine/lexer (v1.0.1)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing egulias/email-validator (1.2.14)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing easyrdf/easyrdf (0.9.1)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing doctrine/inflector (v1.2.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing doctrine/collections (v1.4.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing doctrine/cache (v1.6.2)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing doctrine/annotations (v1.2.7)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing doctrine/common (v2.7.3)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing composer/semver (1.4.2)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing asm89/stack-cors (1.1.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/yaml (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/validator (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/serializer (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/process (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/dependency-injection (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/console (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/polyfill-apcu (v1.4.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing symfony/class-loader (v2.8.26)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing drupal/core (8.3.6)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing drupal/backup_migrate (dev-4.x 99c7620)
Cloning 99c76201a1c64b2ebdd4c3fbb28ec8f676734853
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
- Installing drupal/admin_toolbar (1.19.0)
Loading from cache
> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
zendframework/zend-feed suggests installing zendframework/zend-cache (Zend\Cache component, for optionally caching feeds between requests)
zendframework/zend-feed suggests installing zendframework/zend-db (Zend\Db component, for use with PubSubHubbub)
zendframework/zend-feed suggests installing zendframework/zend-http (Zend\Http for PubSubHubbub, and optionally for use with Zend\Feed\Reader)
zendframework/zend-feed suggests installing zendframework/zend-servicemanager (Zend\ServiceManager component, for easily extending ExtensionManager implementations)
zendframework/zend-feed suggests installing zendframework/zend-validator (Zend\Validator component, for validating email addresses used in Atom feeds and entries ehen using the Writer subcomponent)
symfony/translation suggests installing symfony/config ()
symfony/http-kernel suggests installing symfony/browser-kit ()
symfony/http-kernel suggests installing symfony/config ()
symfony/http-kernel suggests installing symfony/finder ()
symfony/http-kernel suggests installing symfony/var-dumper ()
symfony/routing suggests installing symfony/config (For using the all-in-one router or any loader)
symfony/routing suggests installing symfony/expression-language (For using expression matching)
paragonie/random_compat suggests installing ext-libsodium (Provides a modern crypto API that can be used to generate random bytes.)
easyrdf/easyrdf suggests installing ml/json-ld (~1.0)
symfony/validator suggests installing symfony/config ()
symfony/validator suggests installing symfony/expression-language (For using the 2.4 Expression validator)
symfony/validator suggests installing symfony/intl ()
symfony/validator suggests installing symfony/property-access (For using the 2.4 Validator API)
symfony/serializer suggests installing symfony/config (For using the XML mapping loader.)
symfony/serializer suggests installing symfony/property-access (For using the ObjectNormalizer.)
symfony/dependency-injection suggests installing symfony/config ()
symfony/dependency-injection suggests installing symfony/expression-language (For using expressions in service container configuration)
symfony/dependency-injection suggests installing symfony/proxy-manager-bridge (Generate service proxies to lazy load them)
Writing lock file
Generating autoload files
> Drupal\Core\Composer\Composer::preAutoloadDump
> Drupal\Core\Composer\Composer::ensureHtaccess
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
Generating autoload files
> Drupal\Core\Composer\Composer::preAutoloadDump
> Drupal\Core\Composer\Composer::ensureHtaccess
Next step, you need to add all your contrib modules into your composer.json file so Composer knows where and which version to fetch.
Make a note of all your modules in the /modules directory, then type this command:
composer require drupal/<module_name>
Or if you have a specific module version you want to install, type this line below instead of the one above:
composer require drupal/<modulename>:<version>
Note: replace <module_name> with the module name (for example: admin_toolbar). Same with <version>, replace this with the version number, for example: 1.x-dev (this will get the latest known version of the module).
To uninstall a module, run this command:
composer remove drupal/<module_name>
Another thing, in the composer.json file, it is set to fetch stable version and if it doesn't find a stable version, it will default to fetching any dev release. Some modules have a beta or alpha release which some times can be a bit more stable than dev release. If you come across a module like this, you need to include the version number, otherwise composer will just try and fetch the dev release all the time.
Also note, Composer will place your modules in a directory named contrib, ie modules/contrib/
This is how the directory structure is defined in the Drupal composer.json file. Generally, you should just leave the structure as is. But for whatever reason you want to change this, find these lines:
"installer-paths": {
"core": [
"type:drupal-core"
],
"modules/contrib/{$name}": [
"type:drupal-module"
],
"profiles/contrib/{$name}": [
"type:drupal-profile"
],
"themes/contrib/{$name}": [
"type:drupal-theme"
],
"drush/contrib/{$name}": [
"type:drupal-drush"
],
"modules/custom/{$name}": [
"type:drupal-custom-module"
],
"themes/custom/{$name}": [
"type:drupal-custom-theme"
]
}
},
Ok, repeat this for each module you want to add.
composer require drupal/<module_name>
Composer will add a line for each module into composer.json file so you don't need to. You can open up and double check your composer.json file to see if all the entries for your modules has been added (usually at the top of your file inside:
"require": {
}
if you need to remove any module use:
composer remove drupal/<module_name>
Finally, update your DB and clear the cache using this Drush command:
drush updatedb && drush cr
Now you should be able to use Composer to manage your site.
For more info, check out the doc: Using Composer to manage Drupal site dependencies