A content management system like Drupal provides flexibility and effective workflows to power the content for client journeys as the digital landscape expands to include additional channels and touchpoints. More than a million websites worldwide have chosen it to provide ambitious and fruitful digital experiences.
This tutorial is for you if you want to upgrade to Drupal 10. The different processes to upgrade from Drupal 9 to Drupal 10 are covered in the guide. Let's begin!
Drupal 9 to 10 Upgrade/ Migration
Drupal 10 is built on a more modern core, offering continued security and stability. Check out the step-by-step process guide for the Drupal 10 upgrade.
1.Prepare to upgrade
Start by confirming the hosting environment and ensuring it is compatible with Drupal 10's platform requirements by installing or upgrading to Drupal 9.4.x or 9.5.x.
Next, manage altered scaffold files. When Drupal 9 to 10 is upgraded, all core files—including .htaccess files—should change. Make a note of any modifications you made to the scaffold files and ensure that they have been reapplied following the upgrade. Resolving deprecated Drupal core modules and themes is also crucial.
As several Drupal core modules and themes are deprecated in Drupal 9 and removed from Drupal 10, check for deprecated and obsolete extensions. It includes the Seven admin theme and CKEditor module (for CKEditor 4). One option is to stop using the deprecated modules in Drupal 9. For example, if you use Bartik as the default theme and CKEditor, switch to Olivero and CKEditor 5 before upgrading to Drupal 10. The other option is to install the contributed versions of the extensions when you upgrade the code to Drupal 10 before running database updates.
2.Update contributed modules and projects
It is time to update all contributed modules/projects to make them Drupal 10 compatible. You should use Upgrade Status to check the compatibility of contributed modules/projects and alternate between running the Upgrade Status report and updating modules via Composer until the report finds that all contributed modules/projects are compatible with Drupal 10.
Note: Updated contributed modules/projects that are Drupal 10 compatible will still be compatible with your Drupal 9.4+ site.
The easiest way to update a module to the latest compatible version is to use Composer require instead of update. This ignores the current version constraints set for the module/project in composer.json. For example:
composer require drupal/webform:^6.2 --no-update
If Upgrade Status reports that your site has contributed modules that are not yet compatible with Drupal 10, you can manually check modules identified as needing help from the maintainers.
Note: In some cases, there are Drupal 10 compatible versions that Upgrade Status may not identify. Require the module via Composer to update to the latest compatible version. For example:
composer require drupal/webform:^6.2 --no-update
You can also look in the module/project issue queue for a patch that will make it compatible. Use that patch to update the project. Click here for more details on how to handle this situation.
You may also realize some modules are only compatible with Drupal 10. In this scenario, modify your composer.json file to allow the version required by D9 or the new version required by D10 by using Composer's logical OR operator. This will simplify the upgrade process and avoid dependency issues when following the Drupal upgrade steps. For example:
In composer.json, modify
"drupal/remove_http_headers": "^1.0"
to
"drupal/remove_http_headers": "^1.0 || ^2.0"
Note: Some tools, such as Drupal Console (drupal/console) are not Drupal 10 compatible and should be removed:
composer remove drupal/console --no-update
Once you find that the Upgrade Status reports that all contributed modules/projects are compatible with Drupal 10, uninstall the Upgrade Status module and then remove it:
drush pm-uninstall upgrade_status -y
composer remove drupal/upgrade_status --no-update
Note: You can also prefer to remove Drush altogether before updating and re-install after the update. It prevents issues with updating both Drupal core and Drush simultaneously, which can happen.
3. Update custom modules and themes with Upgrade Status and Drupal Rector
For custom modules and themes, update them using Upgrade Status and Drupal Rector before upgrading to Drupal 10.
4. Upgrade to Drupal 10
Perform the following steps from your Drupal site's root. In this tutorial, we update Drupal 9.5.x to Drupal 10.x. Here is a step-by-step guide to upgrade to Drupal 10.
- You should temporarily add write access to protected files and directories.
chmod 777 web/sites/default
chmod 666 web/sites/default/*settings.php
chmod 666 web/sites/default/*services.yml
- Now, you should update the required versions of the core-recommended packages. Here, we are going to use --no-update to avoid a chicken-and-egg problem with mutual dependencies:
composer require 'drupal/core-recommended:^10' 'drupal/core-composer-scaffold:^10' 'drupal/core-project-message:^10' --no-update
If you have a separate requirement for drupal/core in your composer.json, remove it.
composer remove drupal/core --no-update
If you have drupal/core-dev installed:
composer require 'drupal/core-dev:^10' --dev --no-update
- Now, test perform the update to code with the --dry-run option:
composer update --dry-run
If you encounter any errors, we have covered common issues in the next section. You can check it from there and resolve any issues you encounter. Once resolved, resume the process.
You can also run the command below if you do NOT want to update all your modules, just core and dependencies.
composer update "drupal/core-*" drush/drush --with-all-dependencies --dry-run
Next, perform the update to the code itself:
composer update
- Once you can run composer update without errors, run composer install.
Note: It ensures that any other developers on the project and/or any deploy scripts you may have will not throw errors when installing the new dependencies.
composer install
Now, there will be no errors, and you also see "Nothing to install, update or remove."
- Once you run the composer, install without errors, and run any pending database updates, either by visiting /update.php in the browser or with Drush:
drush updatedb
If there are any errors, you must resolve them and rerun drush updatedb until all updates run successfully.
- When complete, restore read-only access to the sites/default directory:
chmod 755 web/sites/default
Note: It sets the permissions of the directory "default" located within the "website" directory to allow the owner to have read, write, and execute permissions, and for group and others to have read and execute permissions.
chmod 644 web/sites/default/*settings.php
Next, enter the following command.
chmod 644 web/sites/default/*services.yml
Note: It sets the permissions of all files ending with services.yml within the web/sites/default/ directory to read and write for the owner and read-only for the group and others.
4. Common Issues Encountered
Here is a list of common issues encountered:
- If composer update fails with a "Your requirements could not be resolved to an installable set of packages" error, update other dependencies of your project in order to update Drupal core. You can do it with the following command to re-require all of your dependencies, resetting the version constraints currently set in composer.json:
composer show --no-dev --direct --name-only | xargs composer require --no-update
Alternatively, run composer show --no-dev --direct --name-only | xargs to print out a list of your dependencies. If any of your dependencies are only compatible with the current release of Drupal core via an RC or alpha version, add the RC or alpha version specification to your list (e.g.drupal/native_lazy_loading:@RC or drupal/menu_breadcrumb:@alpha). You can also add the explicit :^10 specification to Drupal core packages if Drupal 11 has already been released, but you are trying to update to Drupal 10. Now run composer require --update-with-dependencies with your whole list of dependencies appended to the command. It is time to attempt to run composer update again.
Note: It will be helpful to see all the dependencies that prevent the upgrade to Drupal 10. To do so, run the command:
composer why-not drupal/core ^10
Continue alternating between running composer update and explicitly requiring a Drupal 10 compatible module version until you no longer see the error message. At this point you should see Composer remove the old versions of your dependencies and download the new versions.
- If you use Composer to apply patches (using cweagans/composer-patches), you may find that some patches no longer apply.
- If the patch has been committed to Drupal core or a contrib module, and the issue is closed, remove it from composer.json.
- If a new patch has been created for the later core version, update composer.json with the new patch link.
- A Warning, “the lock file is not up to date with the latest changes in composer.json” message can sometimes be fixed by deleting composer.lock file and vendor folder, and running the composer update command again.
5. Post-upgrade tasks
Here is a list of post-upgrade tasks that you need to follow to upgrade from Drupal 9 to Drupal 10.
- Export configuration
If you are using configuration management, export and commit configuration. Upgrading Drupal core can cause configuration to be overridden due to database updates or YML properties being ordered differently. Before committing, run git diff and verify that the changes will not break/remove functionality.
- Run PHPCS
If you use PHPCS (run PHPCS), apply any automated fixes and manually make any recommended fixes.
- Run tests
If you have custom tests (PHPUnit, Behat, etc.) for your site, run them to verify that site functionality has not been broken.
- Manually test site functionality
You can start tailing Drupal watchdog error log with the command:
drush watchdog:tail
Load your site in a browser and thoroughly test for expected functionality. Fix errors as needed. You can also check errors by running database updates or by running cron:drush updatedb -y
drush cron
Switch to Drupal 10 to ensure a more robust and future-proof website. Drupal 10 offers a more user-friendly experience for content creators and site visitors, providing improved user experience, enhanced content creation, accessibility, multilingual support, and more. With Drupal, you can leverage a customized approach and a faster, streamlined workflow more efficiently.