I started using Drupal 8 from early on. Since Drupal 8.2, it has made Composer and undeclared dependency. I realized I could no longer install modules and manage dependencies in a sane way, as well as update my sites, without converting them to use Composer. Converting the sites to use Composer can be hard if you have issues with your site, like missing modules or broken configuration. If your site is healthy, though, following the next 10 steps should not be hard.
1. Back up the code base and database.
First things come first.
2. Save the list of installed modules.
On your old site, run
$ drush pm-list --type=Module --status=enabled to get the list of the modules that you have enabled. Remove from that list the core and the custom modules. Save this list for later.
3. Get the drupal-project files.
Create an empty folder, navigate there, and run
$ git clone https://github.com/drupal-composer/drupal-project.git
This will clone the drupal-project files. You will use drupal-project as a basis.
4. Take care of the folder structure.
Drupal-project stores some data outside the main codebase folder. To make your site compatible with drupal-project, you need to have your codebase folder inside you root folder. Drupal names it’s codebase folder drupal by default. Drupal-project names it web.
Create a root folder (I will call it root folder, though in reality I call it the name of the site, like, mysite). Place your main codebase folder in it, and rename that codebase folder to web. Then, your folder structure with the index.php file will be something like mysite/web/index.php.
The contents of your root folder should be something like this:
Copy the contents of the drupal-project folder into the root folder, so that the web folder becomes at the same depth with the drush and scripts folders, and the composer.json file.
If you don’t have the custom and contrib folders in the modules folder, create them, move the modules into corresponding folders, and run
$ drush cr in the web folder. Latest Drupal 8 will rescan the changed module paths gracefully. This is needed because composer will install the modules into those paths, so we need to have the paths compatible.
5. Handle the composer entries.
Now here comes the tricky part. By default, Drupal uses composer.json from it’s codebase root folder. Now that you have renamed that folder to web, you have two composer.json files - one in the web folder, and one in the root folder.
We will use the file in the root folder. But before you delete the composer.json from the codebase folder, check out it’s required section and move over the needed entries into the root folder composer.json file. Those can be modules and libraries you installed with composer.
After you have copied everything you need between the old and the new composer.json files, delete composer.json and composer.lock from the codebase folder. These files store the names and versions of required and installed packages. Drupal-project uses different versions, so we moved over the required entries if any and deleted the old files.
6. Delete the vendor folder from the codebase folder.
The vendor folder is where the actual libraries are stored. Delete it from the codebase folder, and we will recreate another in the root folder later. Do not move it over, but delete it.
7. Run composer require from the root folder.
Exit to the root folder and run
$ composer require. Composer will scan the contents of the composer.json file and install the needed libraries into the vendor folder.
8. Take care of the contrib modules.
Create a composer require command from the modules that you had installed, excluding core and custom module names. The command may looks something like this:
$ composer require drupal/admin_toolbar drupal/admin_toolbar_tools drupal/adminimal_admin_toolbar drupal/ctools drupal/ctools_block drupal/entityqueue
If you end up having an error saying that this or that module was not found in a remote repository, remove it from the list. Some rare modules were never uploaded into a Drupal Composer repository, so the can not be managed with Composer. If you have unmanaged contrib modules, you probably want to edit the root folder’s .gitignore file to allow the contrib modules folder to be version-controlled.
Once you run this require command, Composer will reinstall the modules with their dependency libraries, and add them to the autoload file. This is what we are basically doing it for.
Some modules may have broken dependencies, like the backup_and_migrate module. You can remove it from composer require command and download it manually.
Now, you should be able to run drush cr from the codebase folder, and the cache should clear without errors.
If you have errors, you should restart the PHP server and your opcache. Sometimes the errors come from the old code cached.
If you have had missing modules, you will have an error at this stage. Resolve the issues that you may have before proceeding further. Once you have a successful drush cr, change the development server’s vhost settings to point to the codebase folder, and make sure you can run the site without errors. Test it for some time. Correct issues if any.
9. Add the changes to git and apply them on your remote server.
You need to be aware, that the fact that you have everything working on the local server will not mean that it will immediately work on the remote server as well. You need to make this change on a remote server at night.
Check out the converted setup from git. You will now have two codebase folders: the old codebase folder and the new web codebase folder.
Delete the web folder from the server and remove your codebase folder to web. Do a
$ git reset --hard HEAD. The idea here is that you have your media files and settings in the old codebase folder. That is why we delete the web folder, rename the old codebase folder to web and then force git to change only those files that need changing in it.
This may look somewhat barbaric, but it’s efficient, and if you have a better idea how to preserve the old files and settings but apply a new codebase on top of it in an efficient way, tell me in comments.
Visit the web folder, and if the old vendor folder is in it, delete it.
Go a level up into the root folder. Run
$ composer require. This is needed because the libraries and managed modules are excluded from git by default. So unless you remove those .gitignore entries, you will need to run composer require to have those modules and libraries installed. As you run the command, Composer installs the same set of modules and libraries that you have on a development server.
As before, point the vhost, run
$ drush cr in the codebase folder, correct issues if any, and then check the site in the browser. Don’t forget that you may need to restart PHP and opcache.
10. Test thoroughly.
Click around the pages in your site. As an anonymous user. As an admin. Edit pages for different content types, see if they all open without errors. Run cron, see if it completes successfully. Check out in the watchdog if there are any error or warning messages.
Make sure you test the site well before leaving it as completed.