Your own refactoring tool!

Why do you need it?

#1 Change your framework for the new hype one

In JavaScript it's quite common to switch between test frameworks regularly. Sometimes it's easy and sometimes you need to change a lot of code.

For example Jest has provided a few code transformations to migrate from various test frameworks (Chai, AVA, Mocha, ...).

JavaScript
          
describe('foo', () => {
  // ...
});

// ⬇️⬇️⬇️⬇️⬇️

suite('foo', () => {
  // ...
});
          
        

#2 Move from your legacy code

If you use a framework, they may have introduced a breaking change that requires you to change some specific code.

Imagine you had a code transformation to remove your old jQuery? (xtuc/babel-plugin-remove-jquery).

#3 Update your coding conventions

While code styling conventions can be changed easily with tools like Prettier, you will have a hard time changing the code itself.

For example switching from a function declaration to an arrow functions is a common case:

JavaScript
          
function foo() {
  // ...
}

// ⬇️⬇️⬇️⬇️⬇️

const foo = () => {
  // ...
}
          
        

#4 Ahead Of Time optimizations

If AOT doesn't sound familiar to you; the idea is to do the work you can at compile time instead of during the execution, which means less to do at runtime and a performance gain.

For example internationalization or some React optimizations are ahead of time optimizations that you might use without even noticing.

For the requirements of your project you could have to write your own AOT optimization.

#5 Syntactic sugar

If you like debugging using console.log, you will notice that usually we don't have enough information. You could write a simple transformation which does:

JavaScript
          
console.log('foo')

// ⬇️⬇️⬇️⬇️⬇️

console.log('index.js', 'line 83', 'function main', 'foo')
          
        

Note that completely new syntax is more difficult since you will also need to change the parser.

#6 Code generation

Your project could use bindings to some native library, you might want to generate a layer with the same API in JavaScript to more easily interact with it.

How could you do it?

Manually using regexes

Writing a Regular Expressions (RegEx) is simple, but has some big limitations.

Imagine the following example; this piece of code was a common pattern in your company and now you want to get rid of it in your code base. The RegEx /\{([\s\S]*)\}/gm will remove the surrounding curly braces (let's ignore the wrong indentation for now).

JavaScript
          
{
  foo();
}

// ⬇️⬇️⬇️⬇️⬇️

  foo();
          
        
But the following code will not work with this technique:
JavaScript
          
{
    foo();
}
// I comment my code}

// ⬇️⬇️⬇️⬇️⬇️

  foo();
}
// I comment my code
          
        

Of course you could try to handle all types of comments, legit object literals ({a: true}) and nested blocks.

If you are a Vim master

I consider myself as a Vim master, and could record a macro doing the transformation for me. It will probably handle more cases than the RegEx equivalent, but far from all of them.

Not to mention that you will need to actually apply it on your codebase.

Using an Abstract Syntax Tree (AST)

Having an AST allows you to search for specific code in a specific context and make mutations safely.

Unlike the other solutions above, you won't be able to end up with invalid JavaScript code or undefined variables. You also benefit from a better understanding of the JavaScript, like in which scope you are, if a variable is reachable and even hoist declarations.

You can find more information about code transformation with Babel at: babel-plugin-remove-jquery or the babel-handbook.

My Workshop at React Finland

I planned to do a workshop about code transformations and to help you better understand how Babel works at React Finland 2018.

The Babel workshop demystifies how the JSX syntax works in Babel and shows how to create your first plugin using code transformation, type analysis, or other compiler buzzwords.
You can get your ticket here.

Reach out

Say hello: [email protected].

Ping me on Twitter: @svensauleau.