Babelプラグイン開発入門例詳細

6594 ワード

Babel概要
BabelはJavascriptコンパイラであり、コードからコードへのコンパイラであり、通常は「変換コンパイラ」とも呼ばれる.
Babelの作業過程
Babelの処理の主な過程:解析、変換、生成.
  • コード解析詞法分析と文法解析構造AST.
  • コード変換処理ASTは、処理ツール、プラグインなどがこの段階でコード変換され、新しいASTに戻る.
  • コードはASTを巡回してコード文字列を出力します.ですから、ASTに対して一定の理解が必要です.Babelプラグインの開発ができます.
  • AST
    この過程の中で、抽象的な文法ツリー(AST)をめぐって行われます.JavascritpではASTは、簡単に言えば、コード文法構造を記録したObjectである.興味のある方は来てください.https://astexplorer.net/下記のコードのような深い経験をする:
    import {Button} from 'antd';
    
    import Card from 'antd/button/lib/index.js';
    
    ASTに変換したら次のようになります.
    {
      "type": "Program",
      "start": 0,
      "end": 253,
      "body": [
        {
          "type": "ImportDeclaration",
          "start": 179,
          "end": 207,
          "specifiers": [
            {
              "type": "ImportSpecifier",
              "start": 187,
              "end": 193,
              "imported": {
                "type": "Identifier",
                "start": 187,
                "end": 193,
                "name": "Button"
              },
              "local": {
                "type": "Identifier",
                "start": 187,
                "end": 193,
                "name": "Button"
              }
            }
          ],
          "source": {
            "type": "Literal",
            "start": 200,
            "end": 206,
            "value": "antd",
            "raw": "'antd'"
          }
        },
        {
          "type": "ImportDeclaration",
          "start": 209,
          "end": 253,
          "specifiers": [
            {
              "type": "ImportDefaultSpecifier",
              "start": 216,
              "end": 220,
              "local": {
                "type": "Identifier",
                "start": 216,
                "end": 220,
                "name": "Card"
              }
            }
          ],
          "source": {
            "type": "Literal",
            "start": 226,
            "end": 252,
            "value": "antd/button/lib/index.js",
            "raw": "'antd/button/lib/index.js'"
          }
        }
      ],
      "sourceType": "module"
    }
    プラグイン開発の考え方
  • は、処理が必要なノードタイプ
  • を決定する.
  • 処理ノード
  • は、新しいノード
  • に戻る.
    単純プラグイン構造
    プラグインは、公式文書の要求に応じて関数でなければなりません.形式は以下の通りです.
    module.exports = function ({ types: t }) {
        return {
            visitor: {
                ImportDeclaration(path, source){
                    //todo
                },
                FunctionDeclaration(path, source){
                    //todo
                },
            }    
        }
    }
    
    typesは@babel/typesツール類から来ています.主な用途はASTを作成する過程で様々な文法の種類とノード構造を判断することです.
    実施例
    多くの学生がBabel-plug-inmportを使ったことがあります.JSクラスを使って、必要に応じてロードするように助けてくれます.実は、プラグインは以下のコード変換をしてくれました.
    //from
    import {Button } from 'antd';
    
    //to
    import Button from 'antd/es/button';
    import 'antd/es/button/style.css'; 
    
    まず両者のASTの違いを見てみます.変換について明確な認識があるように助けてください.
    変換前:
     
    [{
          "type": "ImportDeclaration",
          "start": 6,
          "end": 45,
          "specifiers": [
            {
              "type": "ImportSpecifier",
              "start": 14,
              "end": 20,
              "imported": {
                "type": "Identifier",
                "start": 14,
                "end": 20,
                "name": "Button"
              },
              "local": {
                "type": "Identifier",
                "start": 14,
                "end": 20,
                "name": "Button"
              }
            }
          ],
          "source": {
            "type": "Literal",
            "start": 28,
            "end": 44,
            "value": "antd/es/button",
            "raw": "'antd/es/button'"
          }
        }]
        
    変換後:
     [{
      "type": "ImportDeclaration",
      "start": 5,
      "end": 41,
      "specifiers": [
        {
          "type": "ImportDefaultSpecifier",
          "start": 12,
          "end": 18,
          "local": {
            "type": "Identifier",
            "start": 12,
            "end": 18,
            "name": "Button"
          }
        }
      ],
      "source": {
        "type": "Literal",
        "start": 24,
        "end": 40,
        "value": "antd/es/button",
        "raw": "'antd/es/button'"
      }
    },
    {
      "type": "ImportDeclaration",
      "start": 46,
      "end": 76,
      "specifiers": [],
      "source": {
        "type": "Literal",
        "start": 53,
        "end": 75,
        "value": "antd/es/button/style",
        "raw": "'antd/es/button/style'"
      }
    }]
    二つの木と比べて、私たちは大体の考えがあるべきです.変換過程において、私達はまたいくつかのパラメータが必要であり、これらのパラメータはプロファイル(package.jsonまたは.babelrc)において、ANtdの必要に応じてロードされるように、いくつかのカスタム構成を提供している.
    ["import",{libraryName:"antd",libraryDireactory:"es","style":"css"}]
    
    今からこのプラグインを実現してみましょう.
    module.exports = function ({ types: t }) {
    return {
        visitor: {
            ImportDeclaration(path, source) {
                
                //    
                const { opts: { libraryName, libraryDirectory='lib', style="css" } } = source;
                //    AST  
                let node = path.node
    
                if(node.source.value !== libraryName){
                    return;
                }
                //           AST
                let newImports = [];
                //     
                path.node.specifiers.forEach(item => {
                    newImports.push(t.importDeclaration([t.importDefaultSpecifier(item.local)], t.stringLiteral(`${libraryName}/${libraryDirectory}/${item.local.name}`)));
                    newImports.push(t.importDeclaration([], t.stringLiteral(`${libraryName}/${libraryDirectory}/style.${style}`)))
                });
                //     
                path.replaceWithMultiple(newImports);                
            }
        }
    }
    )
    今、簡単バージョンの@Babel-plug-in-mportのBabelプラグインが完成しました.興味があれば、もっと多くの内容を知ることができます.Babelプラグインの中国語開発文書は多くの詳細な資料を提供しています.