Exploring Strapi v5 RC: Testing Migration on a Simple Project
If you’re as enthusiastic about Strapi as we are at Notum, you probably know that the release candidate for v5 is already out. As early adopters of new Strapi versions and features, we were curious about the migration process from v4 to v5 and what challenges we might face.
This is crucial for us since we were among the companies with the best know-how on migrating from v3 to v4. That migration was quite complex, but we successfully transitioned many projects, including the Strapi.io website.
Note: This is an update of an article that was initially written upon the release of the beta version. When the release candidate version became available, we consulted with the Strapi team, who provided invaluable assistance in addressing several issues encountered during the migration process. We have decided to publish this article as a follow-up to include the helpful information they shared with us.
We acknowledge that migrating production projects to v5 is not yet recommended because it’s still not a stable version, so please take this article with a grain of salt. It’s meant for informational purposes only, and the migrated project will not be run in production.
Pro tip: If you’re short on time, there’s a summary at the end of the article.
The Upgrade Tool
The Strapi team aims to simplify the migration process by introducing an upgrade tool that performs code mods to automate a large portion of the process.
We tried running the npx @strapi/upgrade@rc to 5.0.0-rc.7 -c 5.0.0 -dy command. A couple of options and commands used here are not yet documented and we had to consult with the Strapi team to get this working. The to command specifies a version you want to migrate to and the -c option specifies the version of codemods. The -dy option just instructs to use debug and answer yes to every prompt.
After running the command we can see that it has updated the dependencies and ran a few code mods so it seems to be working fine.
Looking at one file that has been modified by the code mods we can see that it migrated the files that used the Entity Service API to be using the Document Service API instead which is great. There are still a few things that are marked as TODO but it can definitely speed up the migration process a lot.
Although the migration tool is great we wanted to go through the process manually so in the rest of the article we do not use it.
About the Project
Our goal was to test the migration process on a small and simple project first. We chose a client’s website — https://www.podnikavecesko.cz/. The project includes a few collections but encompasses everything a typical Strapi project would: dynamic zones, components, relations, custom roles, and a few lifecycles with custom logic.
It runs on Strapi version 4.22.1 and is coupled with a Next.js frontend in a turbo mono repo. We use PostgreSQL as the database. In this article, we’ll attempt to migrate the Strapi application to version 5.0.0-rc.7 and see if everything works as expected.
The Migration Process
To begin, we created a fresh v5 project in a different directory to see what had changed. After a brief check, we found that the folder structure and all important files were quite similar, so we decided to upgrade the version of Strapi and other packages made by the Strapi team, such as @strapi/plugin-users-permissions.
Before reinstalling the dependencies, it’s important to delete the .strapi, dist, node_modules, yarn.lock, and cache directories to ensure that everything from v5 is installed.
When running the yarn command to install all dependencies, we encountered several warnings about incorrect peer dependencies, primarily mentioning react-router-dom and styled-components. So, we upgraded those to version 6.0.0, the RC uses from 5.3.3 we were running.
With this resolved, it was time to build the admin panel. As expected, we faced numerous TypeScript errors. Upon inspection, we found that they were mostly type errors or unused @ts-expect-error directives.
After removing the unused @ts-expect-error directives and exploring the Strapi package to find the correct type imports (some were removed as we couldn’t locate them), we rebuilt the application.
Yet another error appeared. This one was perplexing because we had the same dependencies installed as the fresh v5 project in its package.json. We tweaked the dependencies, but nothing worked. So, as any developer would, we searched to see if others had encountered the same issue, and indeed, we found a solution.
The mono-repo setup might be the problem, as others reported similar issues with this setup according to a GitHub issue. So, we took a radical step and copied the entire src directory into another freshly created v5 RC project and added the necessary dependencies to the package.json.
After rebuilding the application again, we still received an error message. However, this time we identified the cause: the @strapi/helper-plugin was deprecated. This package is commonly used by many plugins in the Strapi market, so they probably won’t work with v5 yet. Our only option was to remove these plugins from package.json and plugins.ts, which we did.
Once the plugins were removed, the build was finally completed without issues. So, we started the application by running yarn develop. When running the application for the first time, note that a few migrations run automatically.
The application started without problems, and we were pleasantly surprised that almost everything in the admin panel worked as expected. The data in our collections was intact, and the custom roles, user management, and other important features worked fine.
Database Migration
The Strapi team did an excellent job with automated migrations. Comparing the v4 and v5 databases, we noticed many table names were shortened. For example, “components” is now “cmps” in v5.
Additionally, v5 now uses document_ids, which were automatically generated for our existing content. Therefore, there’s not much to worry about regarding the database.
Migrating the Strapi Codebase
Since our project is very simple and the backend doesn’t contain much custom logic, it started without any problem. If your project is more complex, it might not start up, and you might need to adjust the code first.
In our projects, we used the lifecycle and EntityService API, both of which work differently in v5.
Migrating from EntityService API to DocumentService API is straightforward, as shown below. This is something that will be partially handled by the code mods as shown before.
We also have two simple lifecycles in the project and migrating those is a bit more complex because in v5 we should use the document service middleware instead of lifecycles. In the picture below you can see how the lifecycles looked before the migration.
And this is how it should be implemented with the document service middleware. We have also adjusted the names of the arguments to match the Document Service API naming. Formerly the code lived in a separate lifecycles.js file inside the collection API folder but now everything is in a register function in index.js in the root of the Strapi app. But if you desire to break multiple middleware functions to separate files for better code organization you can still do that.
This covers everything we needed to do to migrate this simple project.
The Frontend
Although this article mainly covers the migration of the Strapi codebase, the frontend will need adjustments too. The significant change is that in v5, the API response is now flattened, and the document ID is expected in requests instead of just the ID.
This means that every request and handling of the response needs adjustment. However, this is a relatively simple task.
Lessons Learned
The migration process seems more convenient than the migration from v3 to v4. The Strapi team did a great job automating many tasks.
To summarize, here are the key points we learned during the process and what to watch out for:
- You might experience issues when running v5 in a mono-repo.
- If you use plugins not made by Strapi, the v5 compatible version is probably not out yet and won’t work.
- You’ll need to resolve imports that are exported (or not exported at all) differently from Strapi v5 and handle TypeScript issues.
- Database migration is automated and works well.
- Table names are shortened compared to v4. For example, “components” is now “cmps” in table names.
- You will need to migrate your backend customization code, especially lifecycles and any parts of the application that use EntityService API.
- Lifecycles need to be migrated to document service middleware.
- The frontend needs to be adjusted to accommodate the new flattened structure of the API responses, and a document ID should now be sent in requests instead of just the ID.
- The upgrade tool works well but do not expect it to do all the work for you.
Please note that your project might require additional work as we tested the migration on a very simple project. If you decide to test the migration yourself, the Strapi v5 documentation has a great resource describing the breaking changes.
Are you considering migrating to v5 and have some questions? Reach us at sales@notum.cz
