Frontend Development 16 min read

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.

ByteFE
ByteFE
ByteFE
Using jscodeshift Codemod to Refactor Large‑Scale Frontend Projects

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/**/*.js

Common 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

frontendASTRefactoringcodemodjscodeshift
ByteFE
Written by

ByteFE

Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.