實作外掛
設定環境
安裝必要的工具鏈
由於外掛程式是用 Rust 程式語言撰寫,並建置成 .wasm
檔案,因此您需要安裝 Rust 工具鏈和 wasm 目標。
安裝 Rust
您可以按照 Rust 官方網站上的「安裝 Rust」頁面(在新分頁中開啟) 中的說明進行操作。
將 wasm 目標新增至 Rust
SWC 支援兩種 .wasm
檔案。它們是
- wasm32-wasi
- wasm32-unknown-unknown
在本指南中,我們將使用 wasm-wasi
作為目標。
安裝 swc_cli
您可以執行以下動作來安裝 SWC 的 Rust-based 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
。例如,visit_mut_ident
針對 foo
和 bar
會由上述 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
的第二個引數。 - 接著你提供輸入檔案路徑和輸出檔案路徑。
記錄
SWC 使用 tracing
來記錄。預設情況下,SWC 測試函式庫將日誌層級設定為 debug
,這可以使用名為 RUST_LOG
的環境變數來控制。例如,RUST_LOG=trace cargo test
會列印所有日誌,包括 trace
日誌。
如果你願意,你可以使用 tracing
的 cargo 功能來移除你的外掛程式記錄。請參閱 文件(在新分頁中開啟)。
發佈你的外掛程式
請參閱 外掛程式發佈指南