今回は、JavaScriptのAST操作ライブラリを探していて、その上でbabelが結構良かったので紹介します。
まずbabelとは
基本的には、新しい記法が使われているJavaScriptを、古い記法のJavaScriptに変換(トランスパイル)するためのトランスパイラーですね。
しかし、実はAST操作が可能な一面もあるんです。
私がbabelをAST操作ライブラリとして見つけた経緯
私は元々、acornとacorn-jsxとescodegenでJSXトランスパイラーを作っていました。
しかし、いくつか問題がありました。
-
JSXElement
等のASTの型が無いため、型宣言が必要 - ASTを作る場合、手動でオブジェクトを作らなければならない
- ノードの探索の整合性が足りない
そのため、いい感じのパーサーが無いかAIに聞き出してみたら、babelを使う方法を提示されました。
そこで、聞き覚えのあるbabelという選択肢を耳にしました。
そこで調べてみたところ、結構素晴らしいライブラリだったところで、
素晴らしいものを見つけた、という感じです。
babelのメリット
1. 全部babelで完結
ASTへのパース、JavaScriptへの変換、ASTの置き換え、AST生成、全てがbabelで完結するため、整合性が高いです。
また、JSXやTypeScriptの変換もプラグイン要らずでそのまま使えます。
2. 長年の信頼
babelは、2014年(10年前)から作られ続けたものです。
そのため、長年使われてきたという信頼があります。
3. 型宣言がしっかりしている
@babel/types
始め、メソッド等の型宣言がしっかりあるため、
TypeScript開発者に良かったり、型網羅や型の整合性が高くなりやすいです。
ASTパース等に使えるbabelモジュール
モジュール名 | 役割 |
---|---|
@babel/generator |
ASTをJavaScriptに戻す |
@babel/parser |
JavaScriptをASTにパースする |
@babel/traverse |
ASTの列挙・置き換えをする |
@babel/types |
ASTを作る・ASTの型情報がある |
使い方のサンプル
以下は、JSXコードをJSXのASTのJSONを文字列リテラルに変換するサンプルコードです。
import { parse } from "@babel/parser";
import traverse from "@babel/traverse";
import generate from "@babel/generator";
import * as t from "@babel/types";
export function transpileJSX(code) {
const ast = parse(code, {
sourceType: "module",
plugins: ["jsx"]
});
traverse(ast, {
JSXElement(ast){
ast.replaceWith(t.stringLiteral(JSON.stringify(ast.node)));
}
});
return generate(ast).code;
}
細かい使い方
細かい使い方は、3番目のメリットの通り型宣言がだいたい教えてくれます。
最後に
acornを使っている・その他のJavaScriptパーサーなどを使っている人は、ぜひbabelを試してみてください。