preface

As a front-end developer, you probably don’t know what Babel is, but for those of you who aren’t familiar with it, HERE’s a brief introduction: The version standard of JavaScript is updated frequently. Since 2015, it has been updated at the rate of one version per year (the version is ES6). Each version standard will introduce some new syntax sugar (decorator syntax, dynamic loading, etc.), which greatly improves the programming experience. There will also be community proposals for the latest features of future ES releases (optional chain calls, etc.) before the next release. These new features or syntactic sugar are not recognized by current browser engines. Therefore, an intermediate tool like Polyfill is needed to compile these new features into degraded syntax, supporting the browser engine without changing functionality. Babel is the best known polyfill tool and has become an important part of the de facto front-end ecosystem.

About the AST

In large projects, Babel configuration is usually done by the big guy, who only needs to write the business code. But if you’re not content to be a page boy, you need to have a deep understanding of this important underlying tool. Babel was able to convert the syntax for us because its built-in tools (ESTree based) statically analyze our source code, parsing JS source code into an abstract syntax tree (AST) with path and node as the base elements. The concept of computer science), for each kind of writing method allowed by JS grammar, there are corresponding description and operation API, through exposed API, you can replace the source code, splicing, compression and other operations, output converted code. To take the simplest example, declare a variable a using the let keyword:

let a = 1;
Copy the code

After conversion by AST tool, the following structure can be obtained (due to space limitations, not all the content is intercepted, incidentally, amway an AST analysis tool AstExplorer, link https://astexplorer.net/, after entering the code, you can directly obtain the object parsed by the code on the right side)

module.exports = function() {
    return {
        visitor: {
            Identifier() {
                console.log("here is identifier"); }}}}Copy the code

Above is a simple Babel plug-in that prints a prompt for each identifier encountered during traversal. Identifier is the built-in js syntax description identifier of Babel, like MemberExpression, FunctionDeclaration, etc., which indicates the operation to be performed when entering a member variable or FunctionDeclaration node.

The sample

Here’s a slightly more complicated example: Source file 1:

function square(n) {
    return n * n;
}
Copy the code

Ast the above code (using astExplorer) :

Plugin content:

module.exports = function({types: t}) {
    return {
        visitor: {
            BinaryExpression(path) {
                if (path.node.operator === The '*') {
                    path.replaceWith(
                        t.binaryExpression('* *', path.node.left, t.NumericLiteral(2))
                      );
                }
            }
        }
    }
}
Copy the code

Output (after Webpack is packed) :

eval("function square(n) {\n  return Math.pow(n, 2);\n}\n\n//# sourceURL=webpack:///./index.js?");
Copy the code

In general, a babels is a function that takes an instance of Babel. Types is the contents of the @babel/core package and is very common during plug-in writing, so destruct assignment is used here and named t variable is used later to refer to types. The plugin’s function is to traverse the syntax tree, enter each binary expression, and when the binary expression’s operator is’ * ‘, replace it with a new binary expression ‘n ** 2’, where Babel does its own transcoding, so the final output is math.pow (n, 2). The complete code is attached at the end of the article. The process of writing a Babel plug-in is as follows: First, do an AST analysis of the object code you want to transform or process to find key nodes and feature expressions; Then modify or delete the node to be processed and find the corresponding method in the API.

For another example, replace the variable name in the function as follows:

function square(n) {
    return n * n;
}
Copy the code

Plugin content:

module.exports = function({types: t}) {
    return {
        visitor: {
            FunctionDeclaration(path) {
                path.scope.rename("n"."x"); }}}}Copy the code

Output content:

eval("function square(x) {\n  return x * x;\n}\n\n//# sourceURL=webpack:///./index.js?");
Copy the code

As you can see, the function variable n is changed to x in the source code. In fact, the Babel plugin also has the concept of scope, which can be used to store local state. Babel documentation is too complex, learning costs are high, for secondary development is not very friendly, to carry out some operations or to be careful, it is best to start from Babel official plug-in source code reading learning. I will follow up with a source code analysis of the Balei plugin. Filling holes article: plugin – proposal – optional – chaining source code analysis — — — — — — — — — — — — — — — — — —

References:

Babel plugin: github.com/jamiebuilds…

Babel types API documentation: www.babeljs.cn/docs/babel-…

AST explorer官网 : astexplorer.net/

The repository for the examples in this article: github.com/dianluyuanl…