How to update legacy React/Angular/Ember/Vue project? [Definitive guide]
Sometimes you will run into a project, that has not been updated for several weeks, or even months! Taking into an account, such project in React, Angular, Vue, Svelte, Ember can have over one hundred of dependencies, it may take some time to update it.
In this definitive guide I will show you how to update legacy project easily. Examples of codes show yarn commands, but almost similar ones you can use for npm.
First of all you should update node. If you have installed nvm (what i recommend), it is very easy to install new versions and switch between them:
nvm install --lts
nvm use LATEST-VERSION-NUMBER
First command installs latest node.js long term support version of node.js. Second line — lists all installed versions. From the list you can find out what is the number of latest LTS. With third line, you switch to the latest version. Just replace LATEST-VERSION-NUMBER with the number discovered with second line of bash code.
Check if application works
You will have to check if application works often during the process. There are two methods you can use. You can run unit tests. If you don’t have them, it’s great to cover the code with unit tests before upgrading. Second method is to execute the application and see if it does not crash. I like to use both methods. But at this point I don’t go into clicking through the application. It is rather a sanity test:
npm run test
npm run start
Tip: before updating anything related to JEST test framework clean cache each time prior to running npm run test:
yarn run clear_jest
Where clear_jest is defined as a package.json script:
"clear_jest": "jest --clearCache"
If something happens, you have to check what is the cause, and fix it. Check documentation for breaking changes, read bugs carefully. Sometimes you have to update version by version. Sometimes you have to go back to previous version if it is impossible to fix. Remember to report all problems on GitHub of node.js so the team can fix problems!
Proper order of updating modules
I like to start with everything that can be updated easily. While updating If i have a problem with any module, I just rollback him to previous working version, and note it down for later. That way the process is very smooth.
The order of updating node modules I use is as follows:
- standalone library modules that are not connected with other modules (eg. day.js)
- language (eg TypeScript)
- testing framework (eg. Jest)
- webpack related modules
- framework related modules
- framework (React, Ember, Angular, Vue, Svelte etc.)
While choosing what versions to update first, I always go with minor updates eg. from 1.2.3 to 1.6.4.
Tip: remember to update @types along with modules if you use TypeScript!
Yarn offers a very nice command that helps update modules. It is:
yarn upgrade-interactive --latest
The command will ignore version numbers in package.json, and display to what version you can max update a module. Also you will see minor updates with green text color, and a link to GitHub, what makes it easy to check out for any breaking changes.
Tip: To speed things up try to update modules in batches of ten, and rollback if necessary.
After updating modules, again check if tests are passing and application starts.
What to do, when update of a module failed?
At this point, module update fail means either tests fail, or application does not start. In such case:
- note down what error you have faced (don’t try to solve the problem now!) and with what version
- set back version of a module in package.json (Source control package.json comparision view in VSCode is very helpful for that)
What to do, when update of a module succeeded?
Hurray! It means tests pass and application starts. For safety reasons save your game with:
git commit -a -m 'ABC-34 partial upgrade'
You will be able to go back to a safe place, if you will face issues later. But since for now everything is good, move on to next modules!
What to do, when you have updated all modules that didn’t cause problems?
At this point you should have updated 90% of your modules. Now you are left with 10% that cause problems. Now, you update them one-by-one and decide how to solve the problem. First, research any issues:
- check if there were any breaking changes between versions (on GitHub) and try to update your code
Tip: It is a good moment to cover your code with specific unit tests to make sure after update your code behaves as before
- check the internet for solutions to errors you receive
Sometimes, you will be able to fix the code. Sometimes you will have to try out previous version of the module. Anyways if you won’t be able to update to latest version, it is a great custom to report a bug on project GitHub, or a detailed question on StackOverflow. It will help other developers, and also help you update module later on.
Protip: I can not go back to previous version of a module!
Sometimes, you will try to go back to previous version of a node.js module, and it will still show the same error as before. It should not happen, since you have went back!
But unfortunately because of a ridiculous design flaw of node modules, dependencies of your module won’t go back.
Fortunately there is an easy way to fix it. All you need to do is remove everything and install everything again:
rm -rf node_modules/
npm cache clear --force
What to do when all modules are done?
At the end of the process you should end up with nicely updated project. Your project should pass all tests, and start properly.
Now you can:
- test if the application really works as expected (human testing)
- save update notes with links to your question and bug reports to the project for you and other developers
- set up a regular process of updating node modules in your organisation (once per month, and with major LTS seems like a reasonable frequency)