One dark night, Yellow asked me Babel do you know?

Me: Damn, Babel, I know. Who are you insulting?

Xiao Huang: Do you know how Babel works?

Me: Of course, the first step is to carry out lexical and grammatical parsing and parse into AST. The second step is to add, update and delete nodes after receiving AST, which is where the plug-in is involved. The third step is to convert the transformed AST into string code.

Xiao Huang: fierce, that you ever write plug-in?

Me: No, I haven’t.

Huang: You haven’t written it yet?

I: I depend, what look in your eyes? Hang on. I’ll give you a wank tonight. By the way, do you have a file?

Yellow: Yes, take the manual of the Babel plugin

What are you doing?

When you say you want to write a plugin, you can’t write 1 + 1 equals 2. Just look at antD content, then make a simple add-on on demand.

// Let's write it this way
import { Button, Table } from 'antd';

//
import Button from 'antd/lib/button';
import Table from 'antd/lib/table';
Copy the code

So, we have a target. What are we waiting for?

Roll up your sleeves and get to work

After a general understanding of the above information, we started to dry.

From our reading, we know that the Babel plug-in requires us to expose a method that returns an object containing a visitor.

module.exports = ({ types: t }) = > {
  visitor: {}};Copy the code

So how do we analyze the code? It’s easy to paste the code into the AST Explorer and analyze the structure of the transformation.

Import {Button, Table} from ‘antd’; import {Button, Table} from ‘antd’; Is an ImportDeclaration node, so we need to operate on that type of node, so in visitor we say this.

module.exports = ({ types: t }) = > ({
  visitor: {
    ImportDeclaration(path) {
      // We can get imported items through the specifiers, source to get which library they imported from
      const { specifiers, source } = path.node;
      // Exclude default import
      if(! t.isImportDefaultSpecifier(specifiers[0])) {}}}});Copy the code

The babel.types used above is a library of tools to help you manipulate nodes better, you can go to the documentation here.

Ok, so now that we have the imported statement, let’s go get what was imported and from what library so we can complete the transformation.

module.exports = ({ types: t }) = > ({
  visitor: {
    // We can get the parameter configuration through the opts in the second parameter
    ImportDeclaration(path, { opts }) {
      // We can get imported items through the specifiers, source to get which library they imported from
      const { specifiers, source } = path.node;
      // Exclude default import
      if(! t.isImportDefaultSpecifier(specifiers[0]) {const declarations = specifiers.map(specifier= > {
          // We can get the imported stuff through specifier.imported
          // Write antd first
          const importPath = `${source.value}/lib/${specifier.imported.name}`;
          // We return an import statement using the above information
          return t.ImportDeclaration(
            [t.ImportDefaultSpecifier(specifier.local)],
            t.StringLiteral(importPath)
          );
        });
        // Replace the import statement generated above with the original statementpath.replaceWithMultiple(declarations); }}}});Copy the code

This is the general process of writing a Babel plugin. Of course, there are many configuration, boundary issues and so on that are not considered in this simple plugin. I uploaded this simple demo to my repository.

Address: github.com/balancelove…