記事ディレクトリ
バベル開発
事前知識
babel を学ぶ前に、理解しなければならない中心的な概念は AST です。
同時に、babel 関連の依存関係がプロジェクトにインストールされていることを願っています。
npm install --save-dev @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill
ASTとは何ですか?
ウィキペディアからの説明:
ASTはどのように見えますか?
AST の基本を理解したら、AST はどのようなものになるでしょうか?
astexplorer.net のWeb サイトでは、オンラインで AST を生成できます。AST の構造を学習するために、AST の生成を試みることができます。
下図のように、左側がコードで、定数 const a = 1 のみが宣言され、右側が AST 構造体です。
バベルプロセス
AST を理解したら、babel の学習を開始できます。
まずbabelは、慣れ親しんだツールとなじみのないツールですが、コードを処理する際に大まかに以下のステップに分けられます。
- 解析、コードの AST コンパイル、コードの AST 構造を取得する
- 要件に従ってコードの AST を変換、処理し、処理された AST 構造を取得します。
- Generate は、AST を元のオブジェクト コードに変換して生成します。
分析する
ソース コードをパーサーを介して抽象文法書 AST に変換します。
この段階の主なタスクは、コードを AST に変換することです。AST は 2 つの段階を経ます。1 つは字句解析と構文解析です。パーサー フェーズが開始されると、最初にドキュメントがスキャンされ、その間に字句解析が実行されます。例: "const a = 1" は、字句解析によって最も細かいトークン( "const"、"a"、"="、"1") に分解されます。
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
言葉の意味から宣言であり、使用kind
はconst
型宣言であることがわかります。フィールドdeclarations
descriptionVariableDeclarator
には、宣言オブジェクトもあります。id は宣言オブジェクトの名前で、これもオブジェクトです。その名前は、宣言オブジェクト名の値です。init は、宣言オブジェクト (またはオブジェクト) の初期化値です。 ) であり、内部の値はこの初期値です。
上記のフィールドに加えて、行、列、値の型などの詳細情報があります。これが取得した AST です。
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 つの手順は既に完了しています。最後に、プラグインは、オブジェクトを返す必要がある関数をエクスポートするだけで済み、トラバース コンバージョン処理段階と同様に、オブジェクトのビジターを変更するだけで済みます。
これは関数であるため、もちろんいくつかのパラメーターを受け入れます。
- api、babel が提供する一連のメソッドを継承
- options は、プラグインを使用するときに渡されるパラメーターです
- dirnameは、処理期間のファイル パスです。
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 アドレス