babel 開発入門 (babel プラグインの開発方法)

バベル開発

事前知識

babel を学ぶ前に、理解しなければならない中心的な概念は AST です。

同時に、babel 関連の依存関係がプロジェクトにインストールされていることを願っています。

npm install --save-dev @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill

ASTとは何ですか?

ウィキペディアからの説明:

コンピューター サイエンスでは、抽象構文ツリー (Abstract Syntax Tree、AST)、または単純に構文ツリー (Syntax tree) は、ソース コードの文法構造の抽象表現です。プログラミング言語の文法構造をツリーの形で表し、ツリーの各ノードはソースコードの構造を表します
「ソースコードの文法構造を抽象的に表現したもの」 、この一文に注目するとASTを理解する鍵となります。この文の一般的な意味は、合意された特定の仕様に従ってツリー状のデータ構造でコードを記述し、JS エンジンとエスケーパーが理解できるようにすることです。
実際、react や vue などのフロントエンド フレームワークの仮想 DOM は、HTML の実際の DOM を JS の仮想マシン DOM として記述します。ページの実際の DOM を変更する操作は、JS の仮想 DOM で実行され、最終的な DOM 構造を取得し、最終的に実際の DOM に反映され、実際の DOM の操作を減らし、ブラウザの消費を減らします。パフォーマンス。基礎となるコードの場合、AST は仮想マシンの DOM に相対的です。
もちろん、ASTはJS独自のものではありません.どの言語も対応するASTに変換できます.AST構造の仕様はたくさんあります.異なる言語は異なる仕様に対応しており,JSで使用される仕様のほとんどはestreeです.この仕様は、 簡単な理解を行うだけです

ASTはどのように見えますか?

AST の基本を理解したら、AST はどのようなものになるでしょうか?
astexplorer.net のWeb サイトでは、オンラインで AST を生成できます。AST の構造を学習するために、AST の生成を試みることができます。
下図のように、左側がコードで、定数 const a = 1 のみが宣言され、右側が AST 構造体です。

バベルプロセス

AST を理解したら、babel の学習を開始できます。
まずbabelは、慣れ親しんだツールとなじみのないツールですが、コードを処理する際に大まかに以下のステップに分けられます。

  1. 解析、コードの AST コンパイル、コードの AST 構造を取得する
  2. 要件に従ってコードの AST を変換、処理し、処理された AST 構造を取得します。
  3. Generate は、AST を元のオブジェクト コードに変換して生成します。

分析する

ソース コードをパーサーを介して抽象文法書 AST に変換します。
この段階の主なタスクは、コードを AST に変換することです。AST は 2 つの段階を経ます。1 つは字句解析構文解析です。パーサー フェーズが開始されると、最初にドキュメントがスキャンされ、その間に字句解析が実行されます。例: "const a = 1" は、字句解析によって最も細かいトークン( "const"、"a"、"="、"1") に分解されます。

字句解析が終了すると、解析された トークンは 文法解析に渡されます。構文解析の主なタスクは、 トークン に基づいて AST を生成することです。 トークン をトラバースし 、最終的に特定の構造を持つツリーを生成します。このツリーは AST です。
const a = 1 例として AST 構造を 取り上げます 。
{
    
    "type":"File","start":0,"end":11,"loc":{
    
    "start":{
    
    "line":1,"column":0},"end":{
    
    "line":1,"column":11}},"errors":[],"program":{
    
    "type":"Program","start":0,"end":11,"loc":{
    
    "start":{
    
    "line":1,"column":0},"end":{
    
    "line":1,"column":11}},"sourceType":"script","interpreter":null,"body":[{
    
    "type":"VariableDeclaration","start":0,"end":11,"loc":{
    
    "start":{
    
    "line":1,"column":0},"end":{
    
    "line":1,"column":11}},"declarations":[{
    
    "type":"VariableDeclarator","start":6,"end":11,"loc":{
    
    "start":{
    
    "line":1,"column":6},"end":{
    
    "line":1,"column":11}},"id":{
    
    "type":"Identifier","start":6,"end":7,"loc":{
    
    "start":{
    
    "line":1,"column":6},"end":{
    
    "line":1,"column":7},"identifierName":"a"},"name":"a"},"init":{
    
    "type":"NumericLiteral","start":10,"end":11,"loc":{
    
    "start":{
    
    "line":1,"column":10},"end":{
    
    "line":1,"column":11}},"extra":{
    
    "rawValue":1,"raw":"1"},"value":1}}],"kind":"const"}],"directives":[]},"comments":[]}

キー部分のスクリーンショットを撮りましたが、下図のようにパッケージの外層typeは でVariableDeclaration言葉の意味から宣言であり、使用kindconst型宣言であることがわかります。フィールドdeclarationsdescriptionVariableDeclaratorには、宣言オブジェクトもあります。id は宣言オブジェクトの名前で、これもオブジェクトです。その名前は、宣言オブジェクト名の値です。init は、宣言オブジェクト (またはオブジェクト) の初期化値です。 ) であり、内部の値はこの初期値です。

上記のフィールドに加えて、行、列、値の型などの詳細情報があります。これが取得した AST です。

では、開発プロセス中にコードを AST に変換するにはどうすればよいでしょうか。これには、以前は Babylon と呼ばれていたbabel が提供する パーサー @babel/parser が必要です。これは、babel チームによって開発されたのではなく、フォークベースのどんぐりプロジェクトによって開発されました。
使用プロセス (babel 関連の依存関係に従って):
const parser = require('@babel/parser');
const ast = parser.parse('const a = 1'); // 转换成AST

詳細については、公式ドキュメントの@babel/parserを参照してください。

変換

パース分析フェーズでは、AST の取得に成功しました。Babel が AST を受け取った後、@babel/traverseを使用して深さ優先トラバーサルを実行します. この段階でプラグインがトリガーされ、ビジター関数の形式で異なるタイプの AST ノードにアクセスします. 上記を例にとると、VariableDeclaration関数VariableDeclarationノードをコールバックできます。このタイプの各ノードは、この関数コールバックをトリガーします。

const parser = require('@babel/parser');

const traverse = require('@babel/traverse').default

const ast = parser.parse('const a = 1'); // 转换成AST

traverse(ast, {
    
    
    VariableDeclaration(path, state) {
    
    
        // 操作处理...
    }
});

この関数には 2 つのパラメーターがあります。

path は、ノード情報、親ノード情報、およびノー​​ドを操作するためのメソッドを含む、現在アクセスされているパスです。これらのメソッドを使用して、ATS の追加、更新、移動、および削除などの操作を実行できます。

state には、現在のプラグイン情報やパラメーター情報などが含まれており、ノード間のデータ転送をカスタマイズするためにも使用できます。

生成

最終段階はgenerateです.sourcemap変換された AST をターゲット コードに出力してsourcemapを生成します。

インスタンス操作

コード学習は見るだけではいけません。深く学ぶには自分でやる必要があります。次に、ES6 から ES5 にconst変換するvar
. 上記の手順に従って、段階的に進めていきます:

解析して AST を取得する

ASTを@babel/parser生成するために比較的簡単です
。これは、 ast 定数が変換された AST である上記のケースと同じです。

const parser = require('@babel/parser');
const ast = parser.parse('const a = 1'); // 转换成AST

変換処理 AST

@babel/traverse処理中のAST を使用する
この段階で、生成された AST 構造を分析し、VariableDeclaration コールバックで kind フィールドが const になることを確認します.kind フィールドを var に変更するだけです。

const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default
const ast = parser.parse('const a = 1'); // 转换成AST
traverse(ast, {
    
    
    // 声明变量都会触发这个VariableDeclaration函数
    VariableDeclaration(path, state) {
    
    
        // 通过 path.node 访问实际的 AST 节点
        path.node.kind = 'var'
    }
});

コードを生成する

最後のステップは、@babel/generator処理された

const parser = require('@babel/parser');

const traverse = require('@babel/traverse').default

const generate = require('@babel/generator').default

const ast = parser.parse('const a = 1'); // 转换成AST
// 转换回code代码
traverse(ast, {
    
    
    // 声明变量都会触发这个VariableDeclaration函数
    VariableDeclaration(path, state) {
    
    
        // 通过 path.node 访问实际的 AST 节点
        path.node.kind = 'var'
    }
});

// 将处理好的 AST 放入 generate
const transformedCode = generate(ast).code
console.log(transformedCode,"new Code")

最終的に印刷された新しいコードの結果は次のとおりです。

プラグインへの開発方法

上記のステップの分析から、私たちが焦点を当てているのは実際には変換処理の段階であることがわかります。したがって、プラグインを開発するときは、この段階に注意を払うだけでよく、webpack プラグインの構成の他の 2 つの手順は既に完了しています。最後に、プラグインは、オブジェクトを返す必要がある関数をエクスポートするだけで済み、トラバース コンバージョン処理段階と同様に、オブジェクトのビジターを変更するだけで済みます。
これは関数であるため、もちろんいくつかのパラメーターを受け入れます。

  1. api、babel が提供する一連のメソッドを継承
  2. options は、プラグインを使用するときに渡されるパラメーターです
  3. dirnameは、処理期間のファイル パスです。
// myplugin.js ファイル、ES6 変数宣言メソッドを var に変換する babel プラグイン コードは次のとおりです。
module.exports = (api, options, dirname) => {
    
    
	return {
    
    
		visitor: {
    
    
            VariableDeclaration(path, state) {
    
    
                path.node.kind = 'var'
            }
	    }
	}
}

開発したプラグインの使い方

プラグインを開発したので、それをどのように使用しますか?
もちろん、babel と webpack を介して使用されます!

1. 最初に webpack をグローバルにインストールし、babel-loader をローカルにインストールします

webpack を使用したいので、開発環境には当然 webpack の指示が必要です (ある場合はスキップしてください)。

npm install webpack -g

プロジェクトファイルをロードするために、webpack に babel-loader も必要です

npm install babel-loader --save
2. webpack.config.js 設定ファイルを書く

エントリ ファイル、使用するローダー、出力ファイルのアドレスなどを指定するなど、webpack 関連の構成を設定することにより、.
コードは次のとおりです。
// webpack.config.js

module.exports = {
    
    
    mode: "development", // 这里使用开发模式,方便查看输出文件内容
    entry: './main.js',
    // output: {
    
    
    //     filename: 'bundle.js' // 可指定输出路径
    // },
    module: {
    
    
        rules: [{
    
    
            test: /\.js?$/,
            use: ['babel-loader']
        }]
    }
}
3.babel プラグインの設定を書く

ステップ 2 webpack が babel-loader によって読み込まれることを確認したら、babel-loader の構成を開始します。babel を構成するにはさまざまな方法がありますが、詳細には触れませんが、ここでは共有メソッドを使用して .babelrc ファイルを介して設定します。
// .babelrc ファイル

{
    
    
    "plugins":[
        ["./myplugin.js"] // 这里以相对路径的方式引入自己写的插件
    ]
}
4. webpack パッケージのコンパイルを実行する

webpack.config.js ディレクトリで、次のコマンドを入力します。

webpack
5. 結果を表示する

エントリ ファイルの内容:

パッケージ化後の出力ファイルの内容:

ご覧のとおり、コードは正常に変換されました。

このケースのコードGitHub アドレス

おすすめ

転載: blog.csdn.net/weixin_43589827/article/details/121798316