Using jscodeshift Codemod to Refactor Large‑Scale Frontend Projects
This article explains how to create and run a jscodeshift codemod that transforms imports of a bulky constants package into per‑constant imports, reducing bundle size in large frontend codebases by leveraging AST parsing, AST Explorer, and automated code modifications.
Background
Maintaining a large‑scale frontend project often requires periodic code refactoring. For example, an npm package an-npm-package-containing-constants provides string constants for tracking events:
export const ConstantsForTrack = {
Track1: 'track_in_scene_1',
Track2: 'track_in_scene_2',
...
};Consumers import it like this:
import { ConstantsForTrack } from 'an-npm-package-containing-constants';
track(ConstantsForTrack.Track1, ...otherParams);As the package grows, its size impacts overall performance. To control bundle size, the export style is changed to individual constants:
export const Track1 = 'track_in_scene_1';
export const Track2 = 'track_in_scene_2';
...Each business module can now import only the needed constants:
import { Track1 } from 'an-npm-package-containing-constants/es/constants';
track(Track1, ...otherParams);Manually updating all import sites is tedious and error‑prone; global IDE replace cannot handle the complexity, and a custom regex script would be hard to maintain. The author therefore turns to the concept of codemod , a tool for large‑scale, semi‑automated codebase refactoring, with official codemods available for React, Vue, and Ant Design.
Related Concepts Introduction
Codemod
Codemod is a tool/library to assist you with large‑scale codebase refactors that can be partially automated but still require human oversight and occasional intervention.
Originating at Facebook, codemod targets massive codebases where a frequently used API changes incompatibly, providing a reliable, semi‑automatic way to rewrite all affected code.
jscodeshift
jscodeshift is a JavaScript/TypeScript refactoring tool based on the codemod idea. It parses code into an Abstract Syntax Tree (AST) and offers APIs to traverse and modify the AST. It combines Babel parser, ast‑types , and recast to preserve code style and supports parallel execution.
Abstract Syntax Tree
An AST is an abstract representation of source code structure, where each node corresponds to a syntactic construct. For example:
if (1 + 1 == 3) {
alert('time to wake up!');
}In the JavaScript ecosystem, ASTs are used not only by engines but also by Babel, ESLint, Webpack, Rollup, etc.
Hands‑on: Write a Codemod
jscodeshift's documentation is limited, so the best way to learn is by building a codemod yourself. The goal is to rewrite the import and usage of an-npm-package-containing-constants as described above.
First, use AST Explorer to visualize the parsed code and locate the ImportDeclaration node whose source.value matches the target package.
Steps to implement the codemod:
Traverse files and select those that import the target package.
Find all member expressions accessing ConstantsForTrack and replace them with the constant identifier, while collecting the used constant names.
Generate a new import statement that imports only the collected constants from .../es/constants and replace the original import.
A minimal codemod skeleton:
module.exports = function (fileInfo, api, options) {
const { source, path } = fileInfo;
const { jscodeshift: j } = api;
const root = j(source); // parse to AST
// write AST manipulation code here
return root.toSource({ quote: 'single' }); // convert AST back to code
};Key code snippets for each step:
Step 1 – Filter files
const trackConstantsImportDeclarations = root.find(j.ImportDeclaration, {
source: { value: 'an-npm-package-containing-constants' }
});
if (!trackConstantsImportDeclarations.length) {
return; // skip file
}Step 2 – Replace member expressions and collect keys
let usedKeys = [];
const memberExprs = root.find(j.MemberExpression, {
object: { name: 'ConstantsForTrack' }
});
memberExprs.replaceWith(nodePath => {
const { node } = nodePath;
const keyId = node.property;
if (keyId.name) {
usedKeys.push(keyId.name);
return keyId;
}
});
if (!usedKeys.length) return;Step 3 – Replace import statement
usedKeys = [...new Set(usedKeys)];
const keyIds = usedKeys.map(key => j.importSpecifier(j.identifier(key)));
const newImport = j.importDeclaration(
keyIds,
j.literal('an-npm-package-containing-constants/es/constants')
);
trackConstantsImportDeclarations.at(0).replaceWith(() => newImport);Run the codemod after installing jscodeshift globally:
npm install -g jscodeshift
jscodeshift -t path/to/your/codemod.js src/**/*.jsCommon CLI options include -c for parallel processes, -d for dry run, --extensions to specify file types, and --parser to choose the parser.
Summary
The article summarizes the most frequently used jscodeshift APIs and provides reference links for AST traversal, node builders, and CLI usage.
AST find & filter: find() , filter()
Collection access: get() , at()
Node insertion & modification: replaceWith() , insertBefore() , insertAfter()
Collection API docs: https://github.com/facebook/jscodeshift/blob/master/src/Collection.js AST node builder docs: https://github.com/benjamn/ast-types/tree/master/def jscodeshift CLI docs: https://github.com/facebook/jscodeshift#usage-cli
References
[1] https://en.wikipedia.org/wiki/Don't_repeat_yourself [2] https://github.com/reactjs/react-codemod [3] https://github.com/vuejs/vue-codemod [4] https://github.com/ant-design/codemod-v4 [5] https://github.com/facebook/codemod [6] https://github.com/facebook/jscodeshift [7] https://github.com/benjamn/ast-types [8] https://github.com/benjamn/recast/ [9] https://astexplorer.net/ [10] https://github.com/facebook/jscodeshift#transform-module [11] https://github.com/benjamn/recast/blob/v0.20.4/lib/options.ts [12] https://github.com/facebook/jscodeshift#collections-and-traversal [13] https://github.com/facebook/jscodeshift#builders [14] https://github.com/benjamn/ast-types/tree/v0.24.7/def [15] https://github.com/facebook/jscodeshift#usage-cli [16] https://github.com/facebook/jscodeshift [17] https://medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb [18] https://www.youtube.com/watch?v=d0pOgY8__JM [19] http://zhangbinliu.me/2017-02-15-fun-with-codemod-and-ast/ [20] https://www.toptal.com/javascript/write-code-to-rewrite-your-code [21] https://www.cnblogs.com/axes/p/7694041.html [22] https://tianqi.name/blog/2018/01/12/jscodeshift.html
ByteFE
Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.