Interviewer: Do you know Babel? Have you ever written a Babel plug-in? A: No. I don’t know much about how Babel works and how to develop plug-ins for Babel.

Basic concept

First of all, we need to understand some basic concepts. This article is very detailed and I will only mention them here.

Babel

Babel is a JavaScript compiler, or rather a source-to-source compiler, commonly known as a “transpiler”. This means that you provide Some JavaScript code to Babel, which Babel changes and returns to you the newly generated code.

AST

Abstract syntax tree (AST for short), or syntax tree (syntax tree), is a tree-like representation of the abstract syntax structure of the source code, specifically the source code of the programming language. The opposite of an abstract syntaxtree is a concrete syntaxtree, often called a parse tree. Typically, during source code translation and compilation, the parser creates an analysis tree. Once the AST is created, information is added during subsequent processing, such as the semantic analysis phase.

Static analysis

Static analysis is the process of analyzing code without executing it (analyzing code while executing code is dynamic analysis). Static analysis has a variety of purposes. It can be used for syntax checking, compilation, code highlighting, code conversion, optimization, compression, and so on.

The three main processing steps of Babel are: parse, transform and generate.

parsing

Receive the code and print the AST. This step is divided into two stages: Lexical Analysis and Syntactic Analysis.

Lexical analysis

The lexical analysis phase transforms the string code into a stream of tokens. You can think of a token as a flat array of syntax fragments. For example, the n*n code is morphed into a token

// n*n
[
  { type: { ... }, value: "n", start: 0, end: 1, loc: { ... } },
  { type: { ... }, value: "*", start: 2, end: 3, loc: { ... } },
  { type: { ... }, value: "n", start: 4, end: 5, loc: { ... } },
  ...
]Copy the code

Each type has a set of attributes that describe the token:

{
  type: {
    label: 'name',
    keyword: undefined,
    beforeExpr: false,
    startsExpr: true,
    rightAssociative: false,
    isLoop: false,
    isAssign: false,
    prefix: false,
    postfix: false,
    binop: null,
    updateContext: null
  },
  ...
}Copy the code

Syntax analysis

The parse phase transforms a token stream into an AST. This phase uses the information in the tokens to transform them into an AST representation structure that makes subsequent operations easier.

This is a process we can go throughastexplorerTo see the AST generated by our code.

At this point our AST is generated, as shown below.



PS: On the left is our source code and on the right is the corresponding generated abstract syntax tree AST.

conversion

The transformation step receives the AST and traverses it, adding, updating, and removing nodes during this process. This is one of the most complex processes in Babel or any other compiler and is where the plug-in will come in.

generate

The code generation step converts the final AST (after a series of transformations) into string code and creates source maps.

Code generation is simple: Depth-first traverses the AST and builds a string that represents the transformed code.

How Babel works is shown below.



How does Babel and the Babel plugin work

Develop a Babel plug-in

Visitors

When we talk about “entering” a node, we really mean that we are accessing them, and we use the term because of the concept of visitor patterns. Visitor is a cross-language pattern for AST traversal. They are simply an object that defines a method for obtaining a specific node in a tree structure.

Const MyVisitor = {Identifier: {// Enter () {console.log("Entered"); }, // Exit () {console.log("Exited!" ); }}};Copy the code

PS: Many times we only need to care about entering the node, we can use the shorthand Identifier() {… } or Identifier: {enter() {… }} instead! This is a simple visitor that, when used for traversal, calls the Enter and exit methods in the Identifier whenever an Identifier is encountered in the tree.

Paths

When we need to modify the information of the corresponding node, we also need to get the information of the corresponding node and the location of the node (that is, the relationship between the node and other nodes). The visitor will pass us the path parameter when it traverses the corresponding node and performs the corresponding function. To help us do the above operations. Note that Path is an object that represents a connection between two nodes, not the current node. We accessed the Identifier node above, and its Path argument looks something like this:

{ "parent": { "type": "VariableDeclarator", "id": { ... },... }, "node": { "type": "Identifier", "name": "..." }}Copy the code

Path.node. name is the name of the current node. Path.parent. Id Gets the id of the parent node. There are many other ways to add, update, move, and delete nodes on a path object that can be documented.

Start writing plugins

The input source code is: YuzhenFan === Wangkemei generated AST

{
  type: "BinaryExpression",
  operator: "===",
  left: {
    type: "Identifier",
    name: "yuzhenfan"
  },
  right: {
    type: "Identifier",
    name: "yuzhenfan"
  }
}Copy the code

Some attributes are omitted, and all attributes can be viewed at astExplorer.net.

Const Babel = require('babel-core') // let MyVisitor = function({types: t}) {return {visitor: { BinaryExpression(path) { if (path.node.operator ! == "===") { return; } // Change the left and right of the current node (the core code of the plugin) pathe.node. left = T. identifier("fanerge1"); path.node.right = t.identifier("fanerge2"); }}}; } const code = `yuzhenfan === wangkemei; `; Let demo = babel.transform(code, {// use our plugins: [MyVisitor]}) console.log(demo); // fanerge1===fanerge2Copy the code

The output code is (processed by our plug-in) :

fanerge1===fanerge2

Here’s how Node prints Balbel’s output:



Project address, very simple Babel plug-in, we will continue to learn

ESTree AST Explorer to explore how Babel and Babel plug-ins work – The Babel plug-in