Migrating an existing website running Drupal 8 or greater into a
Composer-managed build requires you build a composer.json
file including
all the required packages for your website.
The structure of your repository should shift as follows:
The key differences include the new top-level composer.json
and
composer.lock
files, and the top-level location of the vendor
directory.
To compare Composer changes, Acquia recommends you start with a website generally structured the way you want the website built.
docroot/modules/contrib
. If your
modules are not in docroot/modules/contrib
, consider moving
all contributed modules to the specified location.docroot/modules/custom
. If your modules are not
in docroot/modules/custom
, consider moving all custom
modules to the specified location.custom/contrib
structure for themes as for modules.
Each one of the changes may require you to run drush cr
to
ensure your Drupal website knows the new module/theme
location.
Acquia recommends you run drush cr
first to reduce potential
complications migrating to Composer.patches/
directory. The
composer update
command will overwrite all core and contributed
module files, but the command applies patches after an update is
applied. Creating the patches now will save you trouble later.If you have modified the Drupal composer.json
file located at
docroot/composer.json
, you must note the modifications and prepare
to add them to the top-level composer.json
file. The file will be
overwritten, and patching is unnecessary as you can add your
requirements to the top-level composer.json
file.
All the changes should be committed, tagged, and, if possible, merged to master: your new, permanent, file structure.
Create a development branch containing your composer.json
file. Do not create a development branch on master
. The branch
should contain all code required to work on production.
Secure a working template for you to use as reference. Acquia recommends the following template: https://github.com/acquia/acquia-ra-composer/blob/master/composer.json.
Save the file at the top level of your repository: repo/composer.json
.
Note
The instructions in the procedure are based on the
linked composer.json
file.
To simplify the migration, Acquia strongly recommends you install the
exact version of Drupal and all contributed modules already running on
your website. To pin the module to a specific version, open your
composer.json
file, and then edit the require
section based on
the following:
"require": {
"drupal/core-composer-scaffold": "^8.9",
"composer/installers": "^1.0"
},
"drupal/core-recommended": "^8.9"
, to your current Drupal version,
for example, "drupal/core-recommended": "8.9.1"
.
Specifying the entire version is called pinning a package.
Pinning has the advantage of ensuring a specific version is installed,
but pinning also prevents using the composer update
drupal/core-recommended --with-dependencies
command for updates.
Unpin a module after
Composer migration testing is complete.require
section. Start with contributed modules.drush pml --status=Enabled --no-core
If using multisites, inspect all multisites to ensure your contributed module list is complete. Results should display similarly to the following:
Package | Name | Type | Version |
---|---|---|---|
Administration | Admin Toolbar (admin_toolbar) | Module | 8.x-1.19 |
Chaos tool suite | Chaos tools (ctools) | Module | 8.x-3.0-beta2 |
Other | Pathauto (pathauto) | Module | 8.x-1.0-rc1 |
Other | Token (token) | Module | 8.x-1.0-rc1 |
Other | MTM Foundation (mtm_foundation ) |
Theme | N/A |
Other | ZURB Foundation (zurb_foundation ) |
Theme | N/A |
Add each module and theme to the require
section. Using the
previous example, your require
section should display like the following:
"require": {
"drupal/core-composer-scaffold": "^8.9",
"drupal/core-recommended": "8.9.1",
"drupal/admin_toolbar": "1.1.9",
"drupal/ctools": "3.0.0-beta2",
"drupal/pathauto": "1.0.0-rc1",
"drupal/token": "1.0.0-rc1",
"drupal/zurb_foundation": "6.x-dev",
"composer/installers": "^1.0"
},
composer/installers
allows you to
specify, in the extras section, where composer should download
packages of a particular type:"extra": {
"installer-paths": {
"docroot/core": ["type:drupal-core"],
"docroot/modules/contrib/{$name}": ["type:drupal-module"],
"docroot/profiles/contrib/{$name}": ["type:drupal-profile"],
"docroot/themes/contrib/{$name}": ["type:drupal-theme"],
"docroot/libraries/{$name}": ["type:drupal-library"]
}
}
Drupal best practice recommends placing contributed modules in
docroot/modules/contrib
. Your current branch should already
reflect the decision you made before starting the migration process.
If your modules are not in docroot/modules/contrib
, you must
change the installer path by removing /contrib
.
composer.json
file to download its required libraries), you may add
the libraries directly to your require
section. For an example,
see enyo/dropzone
in both the require
section, and in the
installer-paths section of the sample template:
https://github.com/acquia/acquia-ra-composer/blob/master/composer-templates/composer-libraries.jsonCircumventing Composer is easier than creating Composer packages, but if more than one Composer-built website uses your theme or module, creating your custom code as discrete Composer packages may be more efficient and developer-friendly.
In either case, custom code should live in demarcated custom directories:
docroot/modules/custom
docroot/themes/custom
Custom directories allow you to delete the contributed themes and modules by deleting the parent contributed directory entirely, and allowing Composer to rebuild the contributed directory from scratch.
Delete the following directories (including both the directories’ contents and the directories themselves):
docroot/core
docroot/modules/contrib
docroot/themes/contrib
docroot/vendor
Run the following command:
composer install
The composer install
command should install all the packages
required in the composer.json
file into the proper directory, create
a composer.lock
file, and recreate docroot/autoload.php
if the file
does not exist.
Important
The top-level composer.json in turn must define where the web root is located. It does so via the locations mapping, as shown below:
"extra": {
"drupal-scaffold": {
"locations": {
"web-root": "./docroot"
},
...
}
}
.. note::
If you have an existing ``docroot/autoload.php``, you can delete or
manually modify the following path in ``docroot/autoload.php``
to look like the following:
return require __DIR__ . '/../vendor/autoload.php';
Test your now-working website by using git diff
to compare
directories or particular files. Pinned modules or core files
(except autoload.php
) will display little differences. The entire
vendor directory has moved, and the packages in the vendor directory
are different as there may be a more recent version than the version
on your existing website. The changes are fine as the module itself
is the same.
Ensure you check all parts of your Drupal website, noting if
you must run drush cr
, or if modules are missing.
Continue to delete, change the composer.json
file, and install
until your website is fully working.
Whenever your website is ready, you should commit the composer.json
changes, composer.lock
, and all generated code. Remember you are
committing pinned versions of your modules ensuring composer installs
the exact versions running on your existing website. Your next step,
either in the existing branch, or after the existing branch has been
tested and merged to master, is to change all the versioning in the
require
section to use the caret (^
), and more open versioning:
"require": {
"drupal/core-composer-scaffold": "^8.9",
"drupal/core-recommended": "^8.9",
"drupal/admin_toolbar": "^1.1",
"drupal/ctools": "^3.0",
"drupal/pathauto": "^1.0",
"drupal/token": "^1.0",
"drupal/zurb_foundation": "^6.x",
"composer/installers": "^1.0"
},
If you run composer update drupal/core-recommended --with-dependencies
,
Composer will update your website to Drupal 8.9.3
since the preceding
example installed 8.9.1
. Version 8.9.1
is the version you want, but only
after you have tested the migration with pinned versions.