There are many great features that Nuxt offers, from the development experience itself, SSR, Code Splitting, Plugins/Middleware, Typescript support, and the list goes on and on. So why did we decide to migrate our application and what would we have loved to know beforehand?
We decided to migrate for a few reasons. The main reason was the need for SSR to help improve SEO and enable other features such as Dynamic OpenGraph meta tags. The migration was also top of mind as Vue2's EOL(End of life) is approaching and was brought up during some of our recent meetings.
Embarking on a big new project can be fun and exciting, but it's important to reframe from getting shiny object syndrome. Keep in mind the main purpose of migration and the features we want and the reason that sparked this migration in the first place.
The first thing we did was verify that all packages/modules we are using in our project were compatible with Vue 3. This was where the headaches started. At the time of writing this blog post things are getting better, and more and more packages are becoming compatible with Vue 3. With that being said be ready to roll your own solution if needed.
The next thing to check is for breaking changes in the packages/modules you will be updating. There is more than likely a slew of breaking changes in any package you will be updating. Head to the packages website/Github and take note of any breaking changes that will have to be fixed. Luckily for us, the number of breaking changes was minimal.
Vuetify was the package that gave us the biggest headache. From missing documentation, and moving release dates for upcoming/ported components, to the number of changes that needed to be made in the code base. We are very grateful for Vuetify and its contributors, our site would not look as beautiful or cohesive without it!
The heaviest lift of the entire migration was moving and converting the components and pages themselves. The main reason for this was refactoring each page and component from Vue's class-based components to functional components that use the Composition API. This by far took the longest amount of time, but I believe, brought the most value as it improved performance, re-usability, readability, and overall better developer experience.
With Vue being primarily rendered on the client side it's easy to fetch data and await a promise to resolve. Nuxt has a few ways to fetch data, each with different timing.
Nuxt being server-side rendered means Nuxt will fetch your data from the server, render it and send HTML to the client. This is great for SEO but means we have to think about when to fetch data, what data should be fetched on the client or server side, and why.
One reason you may want to fetch some data on the client side instead of the server is client-side authentication systems, such as Firebase. If you're using an authentication system that doesn't use sessions and instead uses a token stored on the client's device, any request that requires auth that is sent from the server will fail.
Testing, oh testing... Testing was another heavy lift, our legacy project had unit tests for each component/page as well as e2e tests using Cypress. Migrating the e2e test was straightforward and fairly easy. Migrating the unit test on the other hand...
We wanted to retain our unit test and wanted to keep refactoring the test to a minimum. With that in mind, we decided to keep Jest as our test runner instead of Vitest. The lack of documentation and other resources made configuring Nuxt, Vue Test Utils, and Jest a sea of errors. Let me know if I should write a post on configuring Jest and Vue Test Utils in Nuxt. We were able to get everything configured and running. The next issue was mocking some of the hooks provided by Nuxt and any auto-imported Nuxt Modules. Hint: auto-imported modules are imported from '#imports'.
The last thing to keep in mind is, where is the project going to live and how are we going to deploy it?
With Nuxt being server-side rendered, your project will require a VPS host such as Heroku, Digital Ocean or AWS. Your Nuxt project can be hosted on a static host like Netlify if you opt for SSG instead of SSR. Also, think about how you will have to configure your CI/CD pipeline to test and deploy this new project.
In conclusion, migrating a monolith application to a new framework or version can be a daunting task, but with careful planning and execution, it can be a success.
The decision to migrate should be driven by specific goals and requirements, such as the need for SSR, improved performance, or staying up-to-date with the latest technology.
During the migration process, it is crucial to carefully evaluate the compatibility of third-party packages, check for breaking changes, and be prepared to roll out custom solutions.
Refactoring components and pages from class-based to functional components can be time-consuming but can bring significant benefits such as improved performance, reusability, and a better developer experience.
Testing and configuring CI/CD pipelines are also important aspects to consider during the migration process. Overall, a successful migration can bring many benefits, including improved SEO, better user experience, and staying up-to-date with the latest technology.