Increment versions in smaller upgrades. Make sure you can run unit tests, end to end tests, and QA on each new version. Also, make sure to read the NodeJS change log to know what APIs change and how they may affect your app. You’ll need to do searches across you codebase to find affected areas.
As you patch this code, ensure your CI process also gets updated since you’ll need to download a new version of Node on your staging/production servers. Tests these as well.
If possible, make a clone of your production database and create a mock production environment. Run requests against this environment. This will give you the best feedback as to whether crashes may occur.
Ensure you can deploy to production in a way that can easily be rolled back. Also, you’ll want to have the right monitoring / logging in place to know when a request crashes your app and how you can reproduce it.
I would frame it as a 1-year project with 3-month chunks
Some sub priorities
- add as much automated testing and pre-running as possible. Use a tool like GhostInspector to add E2E tests quickly
- definitely upgrade in steps, 14 to 16. Try updating to 14 now and see what breaks. Then make a list of libraries or modules to refactor. Dont worry about 18 yet.
- In my organization node-sass has been a blocker for upgrades, along with fsevents. Try to rip those out completely if you can
- If there's any small parts of the app that can be broken out into its own service, now's a good time to try that. Often those smaller parts can run on Node 16 easily
- Good time to implement Prettier and Eslint.
Big thing is you're introducing a "platform" initiative into the organization, get everybody in the mindset of small improvements and upgrades done often. Maintenance should be everybody's job
is there a business need to rewrite it? like, are there existing bugs or new features to be added? because if not, the rewrite doesnt make any sense.
I'm currently migrating an ancient codebase of mine from Node 0.X to the most modern Node I could find. I'd just make the big jump, assuming that things aren't that broken.
Here's the process I followed:
- Ensure that all the tests are passing at the start to have something to compare against.
- Run some manual functional tests to cover gaps in the test and document how the old system worked
- Migrated everything to the latest code standards, one at a time, testing at each stage: ES6 modules, classes, etc (this might not apply for your codebase if it's modern enough)
- Migrated deps to modern ones, one at a time, testing between each one
- Migrated the toolchains to modern ones (ie: rollup, etc - whatever you decide on for your cases)
- Migrated tests to modern test libraries. This step might be moved earlier depending on whether the testing libraries support the older version of Node.
It's not painful, but it's somewhat tedious. May as well make that jump as large as possible, and consider just jumping to a non-LTS version of node if you're going to be actively maintaining it. I prefer LTS for projects that are going into hibernation while running (mostly just bugfixes and minor tweaks - not active changes).