Refactoring massive codebases can be messy, expensive, and tedious, which is why many engineering teams decide it simply isn’t worth doing, especially when dealing with a pattern that is undesirable but still “works.”
An undesirable pattern, for example, could be a function you wrote that is better off being split up into multiple methods, one that would be much easier to use with a few more optional parameters, or one that should ideally return a structure containing more information instead of the boolean value it currently does.
Enter Codemod, a Python tool built to assist large-scale codebase refactors. It can even partially automate the process, although human oversight and occasional manual interventions are still necessary.
Built by developers at Facebook, it was released as open-source software and can be utilized by anyone who wants to introduce sweeping changes to a mature codebase in a sane and systematic manner.
You can install Codemod using your favorite Python package manager, like so:
pip install codemod
You can also install the package system-wide with sudo:
sudo -H pip install codemod
Let’s demonstrate the usefulness of Codemod with a quick example. Say we want to deprecate the use of the <font>
tag. We would fire up the command line and run the following:
codemod -m -d /Users/janedoe/reponame --extensions php,html \ '<font color="?(.?)"?>(.*?)</font>' \ '<span style="color: \1;">\2</span>'
For each regex match, a colored diff will be displayed on the terminal. You will then be prompted to either accept the change (that is, replace that instance of the <font>
tag with a <span>
tag), reject it, or edit the given line in an editor.
In this way, using Codemod to refactor your codebase is a lot like performing find-and-replace in your favorite word processor.
Let’s suppose you and your team of engineers have built out the frontend of a product using React. It works well, runs smoothly, and stakeholders want the current product to remain as-is without any major disruptions.
When you started building out the product, the latest version of React was 16.5. But now you’ve just learned about Suspense, a neat component that allows you to “wait” for some particular code — including data, images, scripts, and other asynchronously-loaded elements — to load, and, in the meantime, specify a loading state (e.g., a spinner or some text on the screen) to display.
Here’s a quick example to demonstrate a Suspense use case:
const demoPage = React.lazy(() => import('./demoPage')); // Display a spinner while the page is loading <Suspense fallback={<Spinner />}> <DemoPage /> </Suspense>
The catch is that Suspense is only available in React version 16.6 and beyond, and your entire product is built on version 16.5. Not to mention that your product owner and other stakeholders are going to be furious if you break everything with an update.
So, the situation is hopeless. You’re doomed to an older version forever until React has progressed to the point where there is no choice but totally overhaul and dedicate time and extensive resources to refactor, right?
Wrong. We can use Codemod to facilitate a painless upgrade while still maintaining care and overseeing the changes.
Facebook has provided multiple Codemod scripts that developers can use to initiate refactors.
First, run the following:
npm install --save react@latest
Alternatively, you can also use yarn:
yarn upgrade react@latest
Great! We now have React 16.9 installed and can take full advantage of Suspense.
However, while React 16.9 does not include any breaking changes, there are several unsafe lifecycle methods that were renamed:
componentWillMount
→ UNSAFE_componentWillMount
componentWillReceiveProps
→ UNSAFE_componentWillReceiveProps
componentWillUpdate
→ UNSAFE_componentWillUpdate
So what now?
Run the following:
npm i react-codemod
This will install React-Codemod, a collection of Codemod scripts for use with jscodeshift specifically created to update React APIs. Once you have that installed, you can use a variety of Facebook-provided scripts to help you run clean refactors.
If your application uses many unsafe lifecycle methods, you can use this Codemod for fast and convenient refactoring instead of painstakingly and manually editing them to match the new names:
cd your_app_respository npx react-codemod rename-unsafe-lifecycles
The above will fire up an interactive prompt that you can use to find-and-replace all occurrences of the old lifecycle method naming conventions.
No discussion about React-Codemod can be complete without an introduction to jscodeshift. While we didn’t have to use jscodeshift for upgrading to React 16.9, it is a vital toolkit when working with React Codemod scripts and also JavaScript in general. The tool works by running Codemod over multiple JavaScript (or TypeScript) files.
However, jscodeshift goes well beyond the usual find-and-replace Codemod scripts, enabling developers to make and automate major updates to a codebase. Updates can include things like changing a function signature and then rewriting the code in every instance of the function being called.
You can install jscodeshift by running the following on your command line:
npm install -g jscodeshift
The following example is a simple use case of replacing every occurrence of some variable “foo” with “bar.”
/** * Using jscodeshift to replace all occurrences of variable "foo" with "bar" */ module.exports = function(file, api) { return api .jscodeshift(file.source) .findVariableDeclarators("foo") .renameTo("bar") .toSource(); };
React is a fast-moving library, and it’s critical for developer teams to stay on top of updates while maintaining the integrity of the product and codebase. In this article, we explored Codemod, a Python tool with scripts that provide an interactive way to refactor and upgrade large codebases.
We also reviewed React-Codemod, an npm package containing scripts specific to upgrading React APIs. Finally, we covered jscodeshift, a toolkit based on Codemod that has more powerful automation capabilities.
By taking advantage of these additional tools, you can make refactoring code and React version upgrades easy and painless, allowing your team to enjoy cutting-edge updates without compromising your codebase or slowing down development.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.