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, ...).
describe('foo', () => {
// ...
});
// ⬇️⬇️⬇️⬇️⬇️
suite('foo', () => {
// ...
});
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).
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:
function foo() {
// ...
}
// ⬇️⬇️⬇️⬇️⬇️
const foo = () => {
// ...
}
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.
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:
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.
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.
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).
{
foo();
}
// ⬇️⬇️⬇️⬇️⬇️
foo();
{
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.
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.
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.
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.