Babel under the hood

- 4 mins

Feeling like this should have been something I’d write down 3 years ago, fine you asked for it.

Source Code(babylon) > AST > Modified AST (plugin + babel-traverse)> Compiled Code(babel-generator)

Stage 1: Parsing

Babel takes the source code and convert it into AST(Abstract Syntax Tree) via Babel’s babylon parser.

The AST should look like something below given the sample code: (foo, bar) => foo + bar;:

// AST shortened for clarity
{
    "program": {
        "body": [
            {
                "type": "ExpressionStatement",
                "expression": {
                    "type": "ArrowFunctionExpression",
                    "params": [
                        {
                            "type": "Identifier",
                            "name": "foo"
                        },
                        {
                            "type": "Identifier",
                            "name": "bar"
                        }
                    ],
                    "body": {
                        "type": "BinaryExpression",
                        "left": {
                            "type": "Identifier",
                            "name": "foo"
                        },
                        "operator": "+",
                        "right": {
                            "type": "Identifier",
                            "name": "bar"
                        }
                    }
                }
            }
        ]
    }
}

Stage 2: Transformation

This is where the magic occurs. In this stage, Babel takes the AST from the last step and manipulates it accordingly such that the resultant AST represents a browser suppported code. This stage is taken care by a Babel plugin/preset. Presets are just simply an array of plugins that make it easier to run a whole a set of transforms without specifying each one manually. You could use Babel’s plugin/preset or write your own plugin/preset for your own customised compilation. These plugins use babel-traverse to traverse through the AST and contains the code which defines how to modify/replace the original AST with the new AST. The arrow function’s AST generated in the last step is manipulated to a new AST by traversing through the AST using babel-traverse and replacing the nodes of the AST (this replacement is done by the Babel plugin code). This new AST represents browser supported code for arrow function:

// AST shortened for clarity
{
    "program": {
        "type": "Program",
        "body": [
            {
                "type": "ExpressionStatement",
                "expression": {
                    "type": "Literal",
                    "value": "use strict"
                }
            },
            {
                "type": "ExpressionStatement",
                "expression": {
                    "type": "FunctionExpression",
                    "async": false,
                    "params": [
                        {
                            "type": "Identifier",
                            "name": "foo"
                        },
                        {
                            "type": "Identifier",
                            "name": "bar"
                        }
                    ],
                    "body": {
                        "type": "BlockStatement",
                        "body": [
                            {
                                "type": "ReturnStatement",
                                "argument": {
                                    "type": "BinaryExpression",
                                    "left": {
                                        "type": "Identifier",
                                        "name": "foo"
                                    },
                                    "operator": "+",
                                    "right": {
                                        "type": "Identifier",
                                        "name": "bar"
                                    }
                                }
                            }
                        ]
                    },
                    "parenthesizedExpression": true
                }
            }
        ]
    }
}

State 3: Code Generation

Finally, Babel takes the new AST and change it to browser supported code via babel-generator.

"use strict";
(function (foo, bar) {
  return foo + bar;
});

References

https://medium.com/@makk.bit/babel-under-the-hood-63e3fb961243

Yifan Chen

a junior developer for life

comments powered by Disqus
rss facebook twitter github youtube mail spotify instagram linkedin google pinterest medium wechat