Codemods – The new age saviors for JS developers

Prerequisite knowledge: To comprehend the article in entirety, you should have working knowledge of Javascript and frameworks. 

 

In an antecedent to this blog post, we looked into the basics of Ember deprecations and the effect of it on how we migrate our codebase to the new Ember version. In continuation, we now talk about Abstract Syntax Tree (AST), codemods, and how to migrate your Ember applications to new Ember versions using codemods. 

Codemod is a mechanism to make sweeping changes across your code with ease and effectiveness, assisting in large-scale migrations of the code-base. Codemod implementations can be performed through automated tools such as jscodeshift. Before we study how a tool such as jscodeshift works, it is imperative to know about refactoring, why large-scale refactorings are necessary, and ASTs.

Refactoring

The term refactoring was first introduced by Martin Fowler from ThoughtWorks; he also wrote a seminal book about the topic. According to Fowler, 

Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.

Large-scale refactoring involves a series of small behavior preserving transformations. Each transformation (called refactoring) does little, but a sequence of transformations produces significant restructuring. Each refactoring is small; therefore, it is less likely to go wrong. The system is kept fully functional after each refactoring, reducing the chances that the system is seriously broken during the final restructuring.

The real motivation behind code refactoring is to identify the smells in your code or some hidden issues lurking in the dark for a very long time, which will eventually pop up during a critical moment when your application is performing an important task. This situation can prove costly; it might bring with it maintenance nightmares time and again. It is therefore pertinent to understand the intricate patterns of code causing the troubles and then, apply proper refactoring mechanisms to remove the issues completely.

Code smells: Bad smells in code are certain structures in the code that suggest (sometimes scream for) the possibility of refactoring. Determining what is and is not a code smell is subjective, and varies by the language, developer, and development methodology. In Refactoring, Martin Fowler along with Kent Beck, has identified about 20 different kinds of code smells. They have also catalogued the various refactoring methods that can be applied to remove these code smells from your source code.

Abstract Syntax Tree

AST is a tree representation of the abstract syntactic structure of the source code written in any programming language. Each node of the tree denotes a construct occurring in the source code.

Understanding the AST representations of your source code gives you great leverage in doing a lot of great stuff:

  • You can write your own ESLint rules to enforce code conventions
  • You can write your own JS transpiling code
  • You can write powerful codemods to refactor your codebase

How codemods work 

Codemod does a very simple processing with your source code – it converts your code into AST representations, manipulates nodes in the AST, and converts the AST back to the source code.

The jscodeshift tool

The following diagram represents how the jscodeshift tool transforms your source code into AST and the manipulated AST back to code.

jscodeshift is a toolkit to run codemods over multiple Javascript or Typescript files. To implement transforms using jscodeshift, 

  1. Install the jscodeshift package through npm. 

$ npm i -g jscodeshift

  1. Use the toolkit and run a list of transforms against your source files.

$ jscodeshift -t myTransforms fileA fileB –foo=bar

The toolkit provides a runner and a wrapper around the recast tool (providing a different API). As specified in the diagram, recast is an AST-to-AST transform tool that also tries to preserve the style of original code as much as possible. The runner runs the provided transform on each file passed to it. It also outputs a summary of how many files have(not) been transformed.

recast

recast is a JavaScript syntax tree transformer, a non-destructive pretty-printer, and automatic source map generator. Recast exposes two essential interfaces, one for parsing the Javascript code and the other for reprinting modified syntax trees.

Example on how to use .parse and .print:

Now, you can manipulate the AST and then use recast.print as follows,

var output = recast.print(ast).code; //print modified syntax tree

Codemods in frameworks

Many JS frameworks rely heavily on codemods to make the associated code migrations seamless, so that the developers using the frameworks don’t have to rewrite a significant amount of code when they move on to new APIs or to a new version of the framework itself. Frameworks such as React, Vue, Angular have published a lot of codemods (and codemod tools) to assist the developers to carry out large-scale code migrations for the applications written in the frameworks.

Ember ❤ Codemods

Ember.js, the popular MVC model JS framework relies on codemods for migration from one version to the next. Whenever there is a deprecation or breaking change introduced in the framework, the core team ensures that they have proper backward compatibility and clearly defined migration paths with codemods. Some example codemods from the Ember community are,

ember-cli-update

At Freshworks, for front-end migrations, we usually use the ember-cli-update tool to upgrade our framework libraries and other supporting add-ons. It provides an easy and efficient way to upgrade our single-page application seamlessly because  the tool automatically resolves dependencies. 

After you run the tool, install the new versions of dependencies; the tool also helps you to identify the available codemods for the ember version to which you are upgrading.

ember-cli-update is a command-line tool that updates Ember CLI Ember.js apps and addons (and Glimmer.js apps). You can run this either as a global executable available to all projects or an Ember CLI command on a single project. It  fetches the list of available codemods and the corresponding instructions from ember-cli-update-codemods-manifest.

To install the tool use the command, $ npm install -g ember-cli-update .

To update to the latest version of Ember CLI use the command, ember-cli-update .

To update to a certain version of Ember CLI use the command, ember-cli-update –to <relevant version number> .

After you update the Ember CLI and resolved any issues that might prop up, to run the codemods, use the command, ember-cli-update –run-codemods .

 

References

Videos

Articles

Tools