コンテンツにスキップ
ドキュメント
プラグイン
ECMAScript
はじめに

プラグインの実装

環境設定

必要なツールチェーンのインストール

プラグインは Rust プログラミング言語で記述され、.wasm ファイルとしてビルドされるため、Rust ツールチェーンと wasm ターゲットをインストールする必要があります。

Rust のインストール

公式 Rust ウェブサイトの「Rust のインストール」ページ (新しいタブで開きます)の手順に従ってください。

Rust に wasm ターゲットを追加

SWC は 2 種類の .wasm ファイルをサポートしています。それらは以下のとおりです。

  • wasm32-wasi
  • wasm32-unknown-unknown

このガイドでは、ターゲットとして wasm-wasi を使用します。

swc_cli のインストール

次のコマンドを実行して、Rust ベースの SWC 用 CLI をインストールできます。

cargo install swc_cli

IDE の設定

vscode を使用する場合は、rust-analyzer 拡張機能をインストールすることをお勧めします。rust-analyzer は Rust プログラミング言語用の言語サーバー (新しいタブで開きます)であり、コード補完、コードナビゲーション、コード分析に役立つ機能を提供します。

シンプルなプラグインの実装

プロジェクトの作成

SWC CLI は、新しいプラグインプロジェクトの作成をサポートしています。

実行

swc plugin new --target-type wasm32-wasi my-first-plugin
# You should to run this
rustup target add wasm32-wasi

新しいプラグインを作成し、お好みの Rust IDE で my-first-plugin を開きます。

ビジターの実装

生成されたコードには、

impl VisitMut for TransformVisitor {
    // Implement necessary visit_mut_* methods for actual custom transform.
    // A comprehensive list of possible visitor methods can be found here:
    // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html
}

コード変換に使用されるコードがあります。トレイト VisitMut (新しいタブで開きます) は AST ノードの変更をサポートしており、すべての AST タイプをサポートしているため、多くのメソッドがあります。


次を入力として使用します。

foo === bar;

SWC Playground (新しいタブで開きます)から、このコードの実際表現を取得できます。

{
  "type": "Module",
  "span": {
    "start": 0,
    "end": 12,
    "ctxt": 0
  },
  "body": [
    {
      "type": "ExpressionStatement",
      "span": {
        "start": 0,
        "end": 12,
        "ctxt": 0
      },
      "expression": {
        "type": "BinaryExpression",
        "span": {
          "start": 0,
          "end": 11,
          "ctxt": 0
        },
        "operator": "===",
        "left": {
          "type": "Identifier",
          "span": {
            "start": 0,
            "end": 3,
            "ctxt": 0
          },
          "value": "foo",
          "optional": false
        },
        "right": {
          "type": "Identifier",
          "span": {
            "start": 8,
            "end": 11,
            "ctxt": 0
          },
          "value": "bar",
          "optional": false
        }
      }
    }
  ],
  "interpreter": null
}

BinExpr のメソッドを実装しましょう。次のようにできます。

use swc_core::{
    ast::*,
    visit::{VisitMut, VisitMutWith},
};
 
impl VisitMut for TransformVisitor {
    fn visit_mut_bin_expr(&mut self, e: &mut BinExpr) {
        e.visit_mut_children_with(self);
    }
}

子要素のメソッドハンドラーを呼び出す場合は、visit_mut_children_with が必要であることに注意してください。たとえば、foo および barvisit_mut_ident は、上記の e.visit_mut_children_with(self); によって呼び出されます。

バイナリ演算子を使用して範囲を絞り込みましょう。

use swc_core::{
    ast::*,
    visit::{VisitMut, VisitMutWith},
    common::Spanned,
};
 
impl VisitMut for TransformVisitor {
    fn visit_mut_bin_expr(&mut self, e: &mut BinExpr) {
        e.visit_mut_children_with(self);
 
        if e.op == op!("===") {
            e.left = Box::new(Ident::new("kdy1".into(), e.left.span()).into());
        }
    }
}

op!("===") はマクロ呼び出しであり、さまざまなタイプの演算子を返します。ここでは、"===" というバイナリ演算子を提供したため、BinaryOp (新しいタブで開きます) を返します。詳細については、op! マクロの rustdoc (新しいタブで開きます) を参照してください。

このプラグインを実行すると、次の結果が得られます。

kdy1 === bar;

変換のテスト

プラグインをテストするには、cargo test を実行するだけです。SWC は、フィクスチャテストを容易にするユーティリティも提供しています。

変換の入力と出力を簡単に確認できます。

test!(
    Default::default(),
    |_| as_folder(TransformVisitor),
    boo,
    r#"foo === bar;"#
);

次に、UPDATE=1 cargo test を実行すると、スナップショットが更新されます。

typescript 型ストリッパーの実際のフィクスチャテスト (新しいタブで開きます)を参照してください。

#[testing::fixture("tests/fixture/**/input.ts")]
#[testing::fixture("tests/fixture/**/input.tsx")]
fn fixture(input: PathBuf) {
    let output = input.with_file_name("output.js");
    test_fixture(
        Syntax::Typescript(TsConfig {
            tsx: input.to_string_lossy().ends_with(".tsx"),
            ..Default::default()
        }),
        &|t| chain!(tr(), properties(t, true)),
        &input,
        &output,
    );
}
 

注意すべき点

  • testing::fixture に提供される glob は、cargo プロジェクトディレクトリからの相対パスです。
  • 出力ファイルは output.js であり、入力ファイルと同じディレクトリに保存されます。
  • test_fixture はテストを駆動します。
  • test_fixture に構文を渡すことで、入力ファイルの構文を決定できます。
  • 次に、test_fixture の 2 番目の引数として、ビジターの実装を提供します。
  • 次に、入力ファイルパスと出力ファイルパスを提供します。

ロギング

SWCはロギングにtracingを使用しています。デフォルトでは、SWCのテストライブラリはログレベルをデフォルトでdebugに設定しており、これはRUST_LOGという名前の環境変数を使用して制御できます。例えば、RUST_LOG=trace cargo testとすると、traceログを含むすべてのログが出力されます。

必要であれば、tracingのcargo機能を使用することで、プラグインのロギングを削除できます。ドキュメント(新しいタブで開きます)を参照してください。

プラグインの公開

プラグイン公開ガイドをご覧ください。