If you’re reading this, you probably already know how software rapidly evolves and how easy it’s to encounter a situation where some tools or libraries get updated (or not) and cause conflicts.
Patch-package is a simple yet powerful tool that allows developers to apply patches to third-party npm packages, and commit them in your repository, ensuring that changes aren't lost during the next installation. In this article, we will discuss a real-world situation we faced in a React Native project and how we successfully used patch-package to resolve conflicts we had with two dependencies.
In our specific case, we needed to update XCode to 14.3 in our React Native project. However, this update included a Swift language update that caused our project to fail during the build process due to incompatible syntax used in two libraries: Yoga and react-native-siri-shortcuts. It’s important to note that the changes we needed to apply belong to iOS native code but since these native modules were installed directly by npm, we were able to use patch-package on them.
Initially, we attempted to update the react-native-siri-shortcuts library, but despite finding an issue and related pull request addressing the problem we encountered with XCode 14.3, the author had not released a new version with the fix. Fortunately, the fix was a simple one-line change.
The second library, Yoga, was a little more tricky. Since we were not directly using this library but it was installed by React Native, upgrading React Native to resolve the issue would have introduced potential compatibility problems with other libraries. In this case, the required change was also a one-liner.
Creating a patch with patch-package is super simple. First, make sure to follow the set-up. Once you’re done with it, discard any changes and remove the node_modules directory to ensure that we don’t have any local changes in a library. Then, we run npm install, make the necessary modifications, and run npx patch-package react-native-siri-shortcut. This will run patch-package, which downloads the specified library (in the same version as our package-lock.json or yarn.lock), and compares it with our local changes. If any differences are detected, patch-package generates a .patch file in the /patches folder at the root level of the project. For example, in our case, it created the file /patches/react-native-siri-shorcut+3.2.2.patch. As you can guess by the filename, this patch is specific to the version that we have installed. So, in the future, if we update the library, the patch won’t be useful anymore. To apply this patch automatically, we add and commit this file to our repo, and NPM (starting from version 5) will automatically apply any patches available from /patches directory on every run of npm install.
The patch file is as follows. It describes the differences we’ve made, in the same format as running git format-patch.
With our other library (react-native) the workflow is the same. We make the changes we need, run npx patch-package react-native, and commit the generated .patch file.
As we’ve seen, creating a patch with patch-package is easy and fast, and can help us to move forward to a simple solution when it comes to, and prevent lots of headaches from potential issues that can arise from extensive library upgrades or forking an entire repo.
Its ease of use, combined with the fact that npm automatically applies those patches, makes it ideal for collaborative work environments.
While having an official library update is always preferable, there are situations where such updates are unavailable. In such cases, patch-package proves to be an invaluable tool, providing an effective solution.