Abstract

Today’s front-end industry is dependent on ES6, but the older browsers do not support, the project especially domestic companies need older browsers compatible with lower versions, thanks to Babel, a fantastic tool that allows our ES6 code to run in the older browsers.

Most front-end developers just configure Babel, install plug-ins as needed, etc. I figured there would be very few people who studied how Babel converted ES6 code and how plug-ins worked, so one day I looked into Babel’s principles for a project.

It should be noted that this article does not cover the usage of Babel. There are too many documents on the official website and other articles of this kind. This article will analyze the principle of Babel with a plug-in I once wrote.

Analysis of the

Babel is actually like a normal language compiler that just inputs code. Contrary to what many people think, Babel isn’t just for COMPILING ES6 into ES5. You can compile ES5 into ES6 if you want, or use a syntax of your own (for example, JSX, And the Babel plug-in with this article.) All you need to do is write the corresponding plug-in.

Babel transforms code in three main steps:

parsing

Using Babylon, the parser, it generates an AST (abstract syntax tree) according to the ESTree specification from the input string of javascript code.

conversion

Transform and modify the AST according to certain rules.

generate

Use babel-Generator to convert the modified AST into regular code.

This is how Babel works, pure string input and output, and the Babel plug-in or the preset stage-0,1,2,3, JSX, etc., are the “rules” for the second step transformation.

What is an AST?

In computer science, an Abstract Syntax Tree (AST), or Syntax Tree for short, is an Abstract representation of the syntactic structure of source code. It represents the syntactic structure of a programming language as a tree, with each node in the tree representing a structure in the source code.

An understanding of AST is essential if you want to understand how Babel works, and you should know AST even if you don’t have much experience with code compilation.

We all know that javascript code is made up of a series of characters, and we can tell what a character does by looking at it, such as variable declarations, assignments, parentheses, function calls, and so on. But the computer did not eyes can see, it needs a mechanism to understand the code strings, based on this consideration in order to make people to be able to understand the code, there will be a AST such a thing, it is a mapping of the source code, can in some rules in the mutual transformation, language engine according to the AST can know what is the function of the code.

The following is a simple variable declaration

var a = 1;
Copy the code

When this declaration generates the AST, you get the following tree structure

The body is the information for the body code, and you can see that the VariableDeclaration, the VariableDeclaration, is the declaration details in the declarations array.

You can check out astExplorer.net/. You can type any code on the left and the generated AST will be displayed on the right.

Writing a plug-in

Introduction to the

The plugin written in this article is called babel-plugin-webpack-async-module-name, which is used to name the import() asynchronous module in webpack.

The conversion is to convert the following method calls:

importName('./a.js'.'name-a');
Copy the code

ES6 provides an import() method for dynamically importing modules. However, this method has only one path parameter and no parameters such as naming dynamic modules. However, the WebPack community provides a way to name dynamic modules in Webpack:

import( /*webpackChunkName: 'name-a'*/'./a.js');
Copy the code

Add a line of comment when using, according to the value of webpackChunkName in the comment, combined with the chunkName of the output configured by Webpack, name the module, see the webpack document for details.

However, the compulsion to manually add a comment and the name in the comment on each call was intolerable, so on second thought, Babel can implement a custom method that takes the module name and generates an annotated import() method. This plug-in is used to generate the annotated import() method.

write

Export a function in babel-plugin-xxx.js

module.exports = function(babel) {
  var t = babel.types
  return {
    visitor: {}}}Copy the code

Babel’s plug-in system is based on the visitor pattern, and this function is written to provide an interface to the visitor pattern.

Babel. types contains a series of tools and methods for handling AST. For actual compilation, it is recommended to input the code in astexplorer.net/, compare the differences between AST, and modify AST using babel.types methods.

The first thing you need to know about Babel is what kind of syntax to handle. In this case, it’s function calls. So you can add the CallExpression attribute to the visitor, which means that you are handling function calls.

visitor: {
  CallExpression: function (path) {
    const {node} = path
    if (t.isIdentifier(node.callee, {name: 'importName'{}))const [module, name] = node.arguments
      if (name) {
        module.leadingComments = [{
          type: "CommentBlock".value: `webpackChunkName: '${name.value}'`
        }]
      }
      path.replaceWith(
        t.CallExpression(
          t.identifier('import'),module]))}}}Copy the code

Path is the path of the AST node being processed, and the specific function method called is identified as importName, annotated according to name, and replaced with the new CallExpression using path.replaceWith.

After processing by the Babel plug-in, the AST of importName(‘./a.js’, ‘name-a’) in the code is transformed and commented to the AST of the correct import() method.

generate

This step is to generate normal code based on the new AST generated by the rules defined in the Presets and Plugin options in the Babel configuration.

conclusion

As for how to parse normal code into AST and generate code from AST, I think this is related to the compilation principle of the language. Babel’s parser is just one implementation. The strength of Babel, however, is the rich AST conversion tools it provides.

Finally, this plugin babel-plugin-webpack-async-module-name is an inevitable trend for front-end applications of a certain scale to use code asynchronous loading. If we do not want to write a bunch of require. Ensure ()… For a bunch of stuff or if you want to use import() as an asynchronous module to import and simply customize the module name, try the plugin 😎.

This article is from Babel principles and plug-in development