Understanding JavaScript Compilation


Compiling (or transpiling) modern JavaScript to older ECMAScript-compatible versions has allowed the web to evolve incredibly fast while making us happier developers. But how does the compilation process work? How can we write our own Babel plugins? Let's find out!


Hello everyone and welcome to my talk, Understanding javascript Compilation. Before we start, let me introduce myself briefly. I'm Michele Riva, Senior Architect at NearForm, author of the real-world next.js book, Google Developer Expert, and Microsoft MVP. Today we are going to be talking about compilation, or I should say transpilation. In fact, when talking about compilation, we refer to that process that takes a source code as an input and produces binary code or byte code as an output. In javascript, we are more likely to adopt transpilation. An example is the REST script compiler, which takes correct REST script code as an input and produces proper javascript code as an output, so from one source code to another. We can do the same with Babel, for example. In that example, we have the optional chaining and knowledge operators, which are not supported on older runtimes and browsers. We want to make this code more compatible, so we take this source code, we feed the Babel compiler, and we get the following code as an output, which is still valid javascript source code, which is more compatible with older runtimes. The whole compilation phase takes place in three different steps, parsing, code transformation, and code generation. Let's break them down. Step number one for parsing is tokenization. So we have var foo equals 10, and we divide it into separate tokens, var foo equals 10. And then we can create a parse tree. And here we can see the structure of our program and understand if it's correct or not. The next step would be abstract syntax tree creation. It's quite difficult to understand from this slide, so let me go on the other one. Okay, so this is how it's presented. We have variable declarations at the top, and again, javascript can create multiple variables in a row. In that case, we create just one variable, so we will be ending up having just one variable declaration. So var foo equals 10, it's the variable declaration. We can break it down to all the variable declarations we have, in that case just one. So variable declarator, where we declare that foo is equal to 10. We can break down the variable declarator again in two different parts, the identifier foo and numeric literal, which is 10.

If we were writing like foo equals true, we would have wrote down the Boolean literal instead of the numerical one, or strings or whatever, just for you to understand. While it's quite easy to understand this tree, I guess this one is a bit more challenging to deal with. When reading an abstract syntax tree, we call this process traversing the tree, and it's quite complex on, of course, complex programs.

But luckily, many tools such as Babel, ESLint, Prettier, provide us a nice interface for traversing the tree, which is called the visitor pattern. In that case, with Babel, we are saying, okay, dear Babel, please give me all the variable declarations, or the identifiers, or the numerical literals, and we just print them to the console.

Once we get, for example, all the variable declarations, we can start transforming them. So that's the case. We say, okay, please give me all the variable declarations inside of our code. And if the kind of the variable is a var, just transform it into a let, which is not wise. I'm not suggesting you doing that, but it's a very straightforward example. So that makes things easier for us. So that said, on the left, we have our input, var foo equals 10, and on the right, we have our output, let foo equals 10. As you can see, on line two, we have a constant, and we leave it untouched because it's not a variable. It's a const.

So as you can see on the code, we are not saying if it's constant, please change it to let. So we are not doing that. As I said, the same concept applies to other tools, such as Prettier, ESLint, Babel, JS, Codeshift, and we're going to see them in details right now. With ESLint, we have a similar approach. We say, okay, please, ESLint, give me all the template literals you can find in my code. And if I find one, I can report to ESLint an error, such as, please do not use template literals.

And I can also provide a fix for it, but in that case, if I have an expression inside my template literals, I can say, okay, I'm too lazy for that, so I'm just returning, I'm not fixing this. But if I don't have an expression, I can say, okay, so I don't have expression, I don't have an expression, so no dynamic data inside my template literals, so just change the literals into double quotes. So that's what we are doing now. And on the left, the input, on the right, the output. JS Codeshift, it's another awesome example.

It's a library built by Facebook and maintained by Facebook itself, and it's meant for big refactors, large-scale refactors. And the concept is quite similar. Here we are saying, okay, please, JS Codeshift, find all the identifiers. And if the identifier names contains the old name string, replace it with new name string. This is the case, again, for large-scale refactors. So we have like old name factory, which get refactored into new name factory.

There's also another awesome typescript plugin, which is called T-typescript, which can help us implementing, again, nice transformations on the code. For example, we can say, if there's a binary operation, such as one plus one, please report it to me. And then we can say, okay, this is a binary operation. We are adding two numbers, and instead of compiling to javascript, which will need to do that operation at runtime, do it at compile time. So that's the output. ConsummateSum originally was 10 plus 20. And as an output, we get ConsummateSum equals 30. That's the power of knowing how to traverse an abstract syntax tree and implementing the visitor pattern. And the same, again, applies with Babel, TSLint, Yaslin, Recast, Pretier, JS Codeshift. And there's also an amazing website, which is called ASTexplorer.net, that can really help you debugging your formulas and try to learn more about how to traverse a tree.

So I really want to thank you all for being here. It has been a real pleasure to talk at Node Congress. And these are my social media handlers. So if you want to reach out, I'd be glad to talk with you again about how to refactor code bases and making code transformations. That's what I love to do and to talk about. So thank you again. I hope to see you all soon.

8 min
18 Feb, 2022

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic