I like to read some articles, from which I can learn some scattered things, but it is not comprehensive and detailed enough, and the actual combat is not enough, so I decided to systematically learn Babel, and write down, and then do some actual combat practice.

As for Babel, IT seems that I was contacted by Babel [ˈb ɪbl] when I studied webpack before, and then I am called Babel [ˈb ɪbl], and then I am called Babel [ˈb ɪbl] correctly by Baidu search.

The purpose of Babel

translation

This is the most common feature used to convert the new esNext syntax, typescript, and flow syntax in your code into an implementation based on the syntax supported by the target environment. You can also polyfill apis that are not supported by the target environment.

Code conversion

Babel is a translator that exposes a number of apis that can be used to parse code into the AST, convert the AST, and generate object code.

Babel compilation process

Babel is a source to source conversion, the overall compilation process is divided into three steps:

  • parseParser transforms source code into an abstract syntax tree (AST)
  • transform: traversalAST, calling varioustransformThe plug-inASTAdd, delete and change
  • generate: The convertedASTPrint to object code and generatesourcemap

To make the computer understand the code, parse the source code string, generate an AST, convert the modification of the code into the addition, deletion and modification of the AST, and then print the object code string after converting the AST.

parse

The purpose of the parse phase is to convert the source string into an AST that the machine can understand. This process is divided into lexical analysis and syntax analysis.

Const name = ‘miku39’; The source code is divided into tokens that cannot be subdivided, i.e. Const, name, =, ‘miku39’. This process is lexical analysis, which splits the string into words according to the rules of word formation

The token is then assembled recursively to generate the AST. This process is a syntactic analysis, combining a group of words into objects according to different syntactic structures.

transform

The Transform phase is the processing of the AST generated by Parse. The AST will be traversed. During the traversal process, the corresponding visitor function registered for different AST nodes will be called. Returns a new AST (you can specify whether to continue traversing the newly generated AST). After this walk through the AST, you are done modifying the code.

generate

The Generate phase prints the AST as an object code string and generates sourcemap. Different AST corresponds to different structured strings. For example, IfStatement can be printed as code in if(test) {} format. This generates a string of object code by printing recursively from the AST root node. Sourcemap records the source-to-object code conversion relationship, which allows us to find the source location of each node in the object code.

The parse phase

The parse phase has @babel/ Parser. @babel/ Parser is an API for Babel that converts source code to AST. Babel Parser is called Babylon, which is based on the Acorn implementation and extends a lot of syntax. It supports es Next (now supported by ES2020), JSX, flow, typescript, etc. Parsing of JSX, flow, typescript and other non-standard grammars requires syntax plug-ins.

It provides two apis: Parse and parseExpression. Parse returns File (the entire AST) as the root of the AST, and parseExpression returns Expression (the AST of an Expression) with different granularity.

function parse(input: string, options? : ParserOptions): File function parseExpression(input: string, options? : ParserOptions): ExpressionCopy the code

Detailed options can be viewed in the documentation. In fact, there are two main categories: what is the content of parse and how to do it

What parse does:

  • plugins: specifyJSX, typescript, FlowPlug-ins to parse the corresponding syntax
  • allowXxx: Specifies whether some syntax allows await outside a function, export without declaration, etc
  • sourceType: Specifies whether parsing module syntax is supported, yesModule, script, unambiguousThree values,moduleParse es Module syntaxscriptEs Module is not parsedSyntax, executed as a script,Unambiguous’ parsing es Module syntax depends on whether the content has import and export.

Parse in what way

  • strictModeIs it strict mode
  • startLineWhich line of the source code to parse from
  • errorRecoveryIf an error occurs, whether to record the error and continue to parse
  • tokenWhether to retain token information during parse
  • rangeWhether to add the Ranges property to the AST node

The most common options are plugins and sourceTypes, which can be used to parse the TSX module

require("@babel/parser").parse("code", {
  sourceType: "module",
  plugins: [
    "jsx",
    "typescript"
  ]
});
Copy the code

transformphase

The transform phase is to traverse and modify the AST from Parse with @babel/traverse. Babel traverse package provides traverse methods:

function traverse(parent, opts)
Copy the code

Parent specifies the AST node to traverse, and opts specifies the visitor function. Babel calls the appropriate visitor function while iterating through the PARENT’s AST.

Traversal process

The value of the visitor object is an object or function:

  • If value is a function, then it is the same function that was called when Enter.
  • If value is an object, you can explicitly specify the handler for Enter or exit.

The function takes two arguments, path and state.

visitor: {
    Identifier (path, state) {},
    StringLiteral: {
        enter (path, state) {},
        exit (path, state) {}
    }
}
Copy the code

The call for Enter is made before traversing the children of the current node, and the call for exit is made after traversing the children of the current node.

Can for a single node types, multiple node types through | connection, you can alias specifies a series of node type.

// call traverse(ast, {FunctionDeclaration: {enter(path, state) {}}}) Traverse (ast, {FunctionDeclaration(path, State) {}}) // Traverse (ast, {' FunctionDeclaration | VariableDeclaration '(path, state) {}}) / / traverse by calling through the alias specifies left the various Declaration node (ast, { Declaration: { exit(path, state) {} } })Copy the code

What aliases are available in the type definition of babel-types.

path

Path is the path in the traversal process, retains context information, and has many properties and methods, such as:

  • path.nodePoints to the current AST node
  • Path. The get and path. The setGets and sets the path of the current node property
  • path.parentPoints to the parent AST node
  • Path. getSibling, path.getNextSibling, path.getPrevSiblingGet sibling nodes
  • path.findLook up the node from the current node

These properties and methods get the current node and its associated nodes

  • path.scopeGets the scope information for the current node

This property gets information about the scope

  • path.isXxxCheck whether the current node is of xx type
  • path.assertXxxCheck whether the current node is of type XX. If not, an exception is thrown

The isXxx and assertXxx methods can be used to determine the AST type

  • Path. The insertBefore, path. InsertAfterInsert the node
  • Path. replaceWith, path.replaceWithMultiple, and replaceWithSourceStringReplace the node
  • path.remove Remove nodes

These methods can add, delete, or modify the AST

  • path.skipSkip traversal of the children of the current node
  • path.stopThe subsequent traversal is complete

These two methods can skip some traversal, but of course path’s API is not the only one

state

The second parameter, state, is the mechanism by which data is passed between nodes during the traversal. The plug-in uses state to pass options and file information. We can also use state to store some shared data during the traversal.

generatephase

Once transformed, the AST is printed as an object code string, via the @babel/generator package’s Generate API

function (ast: Object, opts: Object, code: string): {code, map} 
Copy the code

The first parameter is the AST to print

The second argument, options, specifies details to print, such as comments, minified, whitespace

The third parameter is needed when multiple files are combined to print

SourceMaps is usually used in options. SourceMaps are generated only when this option is enabled

const { code, map } = generate(ast, { sourceMaps: true })
Copy the code

conclusion

Babel is a JS translator that transforms es Next, typescript, and other code. It also exposes apis that allow developers to make application-specific transformations. Use Babel’s @babel/ Parser, @babel/traverse, and @babel/ Generator apis, respectively

  • @babel/parserParse the source code, specifying the parse syntax through plugins, sourceTypes, and so on
  • @babel/traverseVisitor functions are used to process the AST through the Enter and exit phases. The AST uses the PATH API and state to pass some data during the walk
  • @babel/generatorPrint AST as object code string, support comments, minified, sourceMaps, etc.

Of course, There’s more to Bebel’s API than that, and you have to learn to extend it bit by bit