Drupal and Composer

Drupal 8 and above recommends using Composer to manage Drupal sites. From initiating projects, installing Drupal core, contributed modules and themes; to updating and managing them, Composer is recommended (but not required).

Hold a bit, Drupal 10 is changing this. Drupal 10 starts the mission to give power back to site builders as they had in Drupal 7. In the strategic initiatives that came alive in Drupal 10, there is a clear mission to make Drupal a favorite tool for low-coding, no-coding site builders even better than they had it in Drupal 7. Two of the initiatives, namely Project Browser and Automatic Updates will allow site builders manage their Drupal sites from the UI without using Composer in the command line, and yet under the hood Composer will still be at play to manage the site's code. They will install modules and themes with Project Browser and update modules, themes and Drupal core with Automatic Updates, both from the UI of their site and it will be recommended practice as these tools will use Composer to manage the codebase under the hood. If they decide at any point to use Composer to manage the site, there will be no problems as the composer.json would have been kept up to date by these tools. So you can write Composer commands in the command line and/or use Project Browser/Automatic Updates interchangeably. It's all in sync! The same composer.json and composer.lock files are updated either way. Project Browser and Automatic Updates did not launch with Drupal 10.0.0 but are expected sometime in a future minor version.

For those that want to use Composer, please read on.

Version 8.8.0 incorporated native Composer support and thus Drupal will no longer rely on third-party projects to set up Drupal with its dependencies.

As of Drupal 8.8.0, Composer project templates (similar to drupal-composer/drupal-project - this template has now been deprecated in favour of the new template as from 8.8.0) are now available as part of Drupal core. These project templates serve as a starting point for creating a Composer-managed Drupal site. Once you have selected a template project and created your own site, you will take ownership of your new project files. Thereafter, future updates will be done with Composer.

The recommended template

drupal/recommended-project

The recommended-project template creates a new Drupal site with a "relocated document root". This means that the files "index.php" and the "core" directory and so on are placed inside a subfolder named "web" rather than being placed next to "composer.json" and the "vendor" directory at the project root. This layout is recommended because it allows you to configure your webserver to only provide access to files inside the "web" directory. Keeping the vendor directory outside of the web server's document root is better for security.

By default this recommended template will create your new project with vendor folder in your project root and it will create a "web" folder for Drupal core, the scaffold files like index.php, update.php, ... and other folders of your site.

If you are installing on cPanel, you already have "public_html" as your web root so using this template to make a default install will generate a "web" folder that is supposed to be your new web-root so you will now have to reconfigure your account to use "web" instead of "public_html" as your web-root.

Well, lots of our clients' host providers use cPanel so how we use this template is we make a modified install like so:

1. On your local development environment, run composer create-project --no-install drupal/recommended-project my-project-directory 

Drupal 10 was released on December 15, 2022 so this by default will initiate a Drupal 10 project. Drupal 9 will be maintained until November 2023. It is recommended that you start all new projects using Drupal 10 because it is the latest and greatest version, but if for any reason you want to install Drupal 9 then run this command instead, create-project --no-install drupal/recommended-project:^9 my-project-directory

The --no-install flag will stop the installation of Drupal upon project initiation.

The template would generate composer.json and composer.lock files inside my-project-directory.

2. Create a folder public_html inside my-project-directory. So your folder structure should look like this:   

    | -my-project-directory

    |  | -public_html

    |  | -composer.json

    |  | -composer.lock

 3. Edit your composer.json's extra section to change your web-root from "web/" to "public_html/" and change every mention of "web/" to "public_html/" in your installer-paths, as illustrated below:

"extra": {
        "drupal-scaffold": {
            "locations": {
                "web-root": "web/"
            }
        },
        "installer-paths": {
            "web/core": [
                "type:drupal-core"
            ],
            "web/libraries/{$name}": [
                "type:drupal-library"
            ],
            "web/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "web/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "web/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "web/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "web/profiles/custom/{$name}": [
                "type:drupal-custom-profile"
            ],
            "web/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        },

Change this ...

"extra": {
        "drupal-scaffold": {
            "locations": {
                "web-root": "public_html/"
            }
        },
        "installer-paths": {
            "public_html/core": [
                "type:drupal-core"
            ],
            "public_html/libraries/{$name}": [
                "type:drupal-library"
            ],
            "public_html/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "public_html/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "public_html/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "public_html/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "public_html/profiles/custom/{$name}": [
                "type:drupal-custom-profile"
            ],
            "public_html/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        },

...to this.

4. From my-project-directory, run composer install to download Drupal and all its dependencies. Drupal will be placed inside public_html. You can go ahead to install the site, set up your custom theme and do some initial site building in local.

5. Now we have to deploy the project to your host server. Push composer.json, composer.lock, sites folder, your custom modules, your custom theme and any other custom libraries and files (that is, all the projects and files you did not download with Composer) to your Git repo. If you prefer FTP to Git it's fine, but wait till after step 7 below before you FTP them.

6. Go on your host server and pull or FTP composer.json and composer.lock on the root of your cPanel account. Your folder structure should look like this:

    | -cPanel-root

    |  | -public_html

    |  | -composer.json

    |  | -composer.lock

7. From cPanel root, run composer install --no-dev The --no-dev switch skips the installation of packages not intended for use in production. Composer will download vendor folder on the cPanel root and place Drupal inside public_html

8. Pull or FTP files folder to overwrite the files folder on the server if you uploaded any files in local that you want on the live site. If you do not want the files uploaded during local development on the live site then ignore uploading the files folder. Pull or FTP your other custom modules and themes and files to your host server.

That's it! You got Drupal 10 installed on your cPanel account.

9. For subsequent management of the site, you would update core, modules and themes with Composer in local, install new modules and libraries with Composer in local, push composer.lock and composer.json to Git repo and pull to cPanel root or transfer with FTP, then run composer install --no-dev from cPanel root. Your code updates or new modules will be installed on your website.

The recommended-project template does not install Drush nor Drupal Console automatically like the deprecated drupal-composer/drupal-project template so you should install Drush by yourself. I recommend you install Drush, it will make your Drupal experience better. To install Drush has now become as easy as composer require drush/drush after which you will call it from vendor/bin/drush. To call it with drush, read my other blog post.

Note: It is not recommended to use Composer to install or update code on live server like running composer require drupal/metatag or composer update drupal/metatag. You should NOT do that on live server. Install and update in local development environment and then push to live server as explained above.

Chau!

Last updated: September 11, 2023