Dependencies serve an important purpose in any application as they reduce the codebase, serve specific functions, and make the process efficient. When it comes to React applications, dependencies are vital for the application. Different packages and modules are used to make different parts of the application functional.
Since these modules are external, they are updated periodically, and as a developer, you should update the packages to the latest version as well.
Why Should You Update Dependencies?
Assuming that our project is running perfectly fine with the currently installed packages, one obvious question that strikes everyone’s mind is, why update the packages in the first place?
The foremost reason is to mitigate security loopholes.
Over time, packages become less security resistant and more prone to vulnerabilities. But it is not just about security. Updated packages also offer better performance and bring in new features.
So does that mean, updating to the latest version fixes security issues without breaking the application? Not necessarily. There are things like package-lock.json and other similar lock files to keep the project stable across different environments, but this adds overhead on the developers as they’ve to manually update packages, even if there are minor updates.
So, the question is: How do you decide which updates break the existing application and how often should one look out for updates?
Clear the Clutter
Before identifying which updates don’t break the project and the frequency of updates, it is important to know which packages need to be updated? This can be found out by simply running, npm outdated, which gives you a list of all the packages that have an update available. Next, running npm update updates all the outdated packages (although it does not update to the major version). Now, that we know how to identify and update outdated packages, how often should one do this?
You should not look for updates because you never know when the updates are rolled out. Moreover, if your codebase has multiple dependencies, looking for updates for all those dependencies manually every day is a tedious and inefficient way to go about it.
As a developer, one should always focus on improving the application and building new features. The task of checking for updates can be outsourced to a third-party tool that notifies us whenever an update is available. Think of this with the analogy of updating a smartphone’s operating system. We do not check for an update every time. Usually, the system notifies us whenever there is an update available.
Renovate to the Rescue
Renovate is an open-source tool that manages dependency updates automatically. With it, you don’t have to manually check for updates every now and then—Renovate keeps an eye out for them and updates stale and outdated dependencies automatically. It is free to use and easy to configure.
Before using it, let us see how it works? There are various ways this tool can be used, but the most favored method is integrating it with GitHub.
Once the Renovate app is added to our project hosted on GitHub, it basically scans the installed dependencies from package.json or package-lock.json and continuously looks for updates. As soon as it finds one, it submits a pull request stating the issue and recommended updates.
Although the title says specifically for React applications, this method can be used with other frameworks too.
Let us see how we can implement Renovate in our project.
Head to their GitHub page linked above, scroll to the bottom and click “Install it for free”.
Next, you’ll have to choose the repositories for which you want Renovate to start looking for dependency updates, you can either manually select some or use it on all of them.
After the installation is complete (barely takes a few seconds), it opens an onboarding pull request to all the selected repositories. I used it on a sample project, and this is how it looked:
Basically, it contains an overview of all the actions Renovate will be performing.
Merging this pull request adds renovate.json, which contains the rules that determine the tool’s behavior. The default configuration will look something like this:
{
“extends”:[
“config:base”
]
}
This extends the default configuration. After this file is added, it starts raising pull requests to update packages.
The pull requests also include the latest release notes, helping you know more about what’s new.
Fine Tuning the Configurations
So far, so good. After a point, even this becomes tiresome, even though much of the task is already abstracted away from the developer.
To overcome this, we can set auto-merge to true so that whenever there is an update available, the Renovate bot auto merges the dependencies with updates. However, this doesn’t differentiate between major, minor, and patch updates. A good practice is to auto-merge minor and patch updates and manually review major updates before approving them. Since major updates are made once in a while, it won’t add much of a burden.
“packageRules”:[
{
“updateTypes:[“minor”,”patch”],
“automerge”:true
}
]
In the above snippet, auto-merge has been set to true for update types minor and patch.
Deciding Which Packages to Update
Up until now, we saw how Renovate can ease the process of updating dependencies.
The next question is how to decide which packages to update and when to update them.
In simple terms, a package can be updated only if it doesn’t break the existing codebase. This can be verified by setting up a workflow. Ideally, the workflow should be verified for all updates including minor and patch updates.
A GitHub action can be set up to perform this whenever a new pull request is created. This also suits our need as Renovate opens a pull request whenever it detects an update. This action considers the changes made in the pull request and executes the workflow with respect to it.
If the workflow test passes with auto-merge set to true, the pull request is safely merged ensuring that the update is not causing any sorts of issues.
Note that this is with regards to package version updates only. Say you’re updating a component package from 1.x.x to 2.x.x, which is a major update. The workflow may be verified, but further adding the newly introduced prop might cause some issues which should be taken care of manually.
Conclusion
Updating dependencies is crucial to keeping an application compatible with the latest features and fixes. At the same time, however, it is equally important to determine which updates make it into the application and which updates do not. Having an automated workflow with suitable configurations helps eliminate manual efforts and also makes updating dependencies easier.