轉譯器
使用 Bun 的轉譯器來轉譯 JavaScript 和 TypeScript 程式碼
Bun 將其內部轉譯器作為 Bun.Transpiler 類公開。建立例項:
const transpiler = new Bun.Transpiler({
loader: "tsx", // "js" | "jsx" | "ts" | "tsx"
});
.transformSync()
使用 .transformSync() 方法同步轉譯程式碼。轉譯器不會解析模組或執行程式碼。結果是一個原生 JavaScript 程式碼字串。
const transpiler = new Bun.Transpiler({
loader: 'tsx',
});
const code = `
import * as whatever from "./whatever.ts"
export function Home(props: {title: string}){
return <p>{props.title}</p>;
}`;
const result = transpiler.transformSync(code);
import * as whatever from "./whatever.ts";
export function Home(props) {
return jsxDEV_7x81h0kn("p", {
children: props.title
}, undefined, false, undefined, this);
}
要覆蓋 new Bun.Transpiler() 建構函式中指定的預設載入器,可以給 .transformSync() 傳入第二個引數。
transpiler.transformSync("<div>hi!</div>", "tsx");
細節說明
.transformSync 會在與呼叫程式碼相同的執行緒中執行轉譯器。
宏 會與轉譯器在同一執行緒中執行,但使用的事件迴圈與應用程式的其餘部分不同。宏和常規程式碼共享全域性變數,因此可以(但不建議)在它們之間共享狀態。在宏之外使用 AST 節點屬於未定義行為。
.transform()
transform() 方法是 .transformSync() 的非同步版本,傳回一個 Promise<string>。
const transpiler = new Bun.Transpiler({ loader: "jsx" });
const result = await transpiler.transform("<div>hi!</div>");
console.log(result);
除非你要轉譯_許多_大型檔案,否則請使用 Bun.Transpiler.transformSync。執行緒池開銷通常比轉譯本身的開銷還要高。
await transpiler.transform("<div>hi!</div>", "tsx");
細節說明
.transform() 方法會在 Bun 的工作執行緒池中執行轉譯器,因此執行 100 次會將工作分散到 Math.floor($cpu_count * 0.8) 個執行緒中,而不會阻塞主 JavaScript 執行緒。
如果你的程式碼使用了宏,轉譯器可能會在該新執行緒中啟動 Bun JavaScript 執行環境的新副本。
.scan()
.scan() 方法掃描原始碼,並傳回其匯入和匯出的列表,以及每一項對應的後設資料。僅型別的匯入和匯出會被忽略。
const transpiler = new Bun.Transpiler({
loader: "tsx",
});
const code = `
import React from 'react';
import type {ReactNode} from 'react';
const val = require('./cjs.js')
import('./loader');
export const name = "hello";
`;
const result = transpiler.scan(code);
{
"exports": ["name"],
"imports": [
{
"kind": "import-statement",
"path": "react"
},
{
"kind": "dynamic-import",
"path": "./loader"
}
]
}
imports 陣列中的每個匯入項都包含 path 和 kind。Bun 將匯入分類為以下幾種型別:
import-statement:import React from 'react'require-call:const val = require('./cjs.js')require-resolve:require.resolve('./cjs.js')dynamic-import:import('./loader')import-rule:@import 'foo.css'url-token:url('./foo.png')
.scanImports()
在對效能敏感的程式碼中,使用 .scanImports() 方法獲取匯入列表。它比 .scan() 更快(尤其是對於大型檔案),但由於效能最佳化,其準確性略低。
const transpiler = new Bun.Transpiler({
loader: "tsx",
});
const code = `
import React from 'react';
import type {ReactNode} from 'react';
const val = require('./cjs.js')
import('./loader');
export const name = "hello";
`;
const result = transpiler.scanImports(code);
[
{
"kind": "import-statement",
"path": "react"
},
{
"kind": "require-call",
"path": "./cjs.js"
},
{
"kind": "dynamic-import",
"path": "./loader"
}
]
參考
type Loader = "jsx" | "js" | "ts" | "tsx";
interface TranspilerOptions {
// 替換鍵為值,值必須是 JSON 字串。
// { "process.env.NODE_ENV": "\"production\"" }
define?: Record<string, string>,
// 此轉譯器的預設載入器
loader?: Loader,
// 預設目標平臺
// 影響 import 和/或 require 的使用方式
target?: "browser" | "bun" | "node",
// 指定 tsconfig.json 檔案,字串化的 JSON 或物件
// 用於設定自定義的 JSX 工廠、片段或匯入源
// 例如,使用 Preact 替代 React,或使用 Emotion
tsconfig?: string | TSConfig,
// 用巨集替換匯入
macro?: MacroMap,
// 指定一組需剔除的匯出項
// 或重新命名某些匯出
exports?: {
eliminate?: string[];
replace?: Record<string, string>;
},
// 是否從轉譯檔案中移除未使用的匯入
// 預設: false
trimUnusedImports?: boolean,
// 是否啟用一系列 JSX 最佳化
// jsxOptimizationInline ...,
// 實驗性空白符壓縮
minifyWhitespace?: boolean,
// 是否內聯常量值
// 通常可以提高效能並減小包體積
// 預設: false
inline?: boolean,
}
// 對映匯入路徑到宏
interface MacroMap {
// {
// "react-relay": {
// "graphql": "bun-macro-relay/bun-macro-relay.tsx"
// }
// }
[packagePath: string]: {
[importItemName: string]: string,
},
}
class Bun.Transpiler {
constructor(options: TranspilerOptions)
transform(code: string, loader?: Loader): Promise<string>
transformSync(code: string, loader?: Loader): string
scan(code: string): {exports: string[], imports: Import[]}
scanImports(code: string): Import[]
}
type Import = {
path: string,
kind:
// JavaScript 中的 import foo from 'bar';
| "import-statement"
// JavaScript 中的 require("foo")
| "require-call"
// JavaScript 中的 require.resolve("foo")
| "require-resolve"
// JavaScript 中的動態 import()
| "dynamic-import"
// CSS 中的 @import()
| "import-rule"
// CSS 中的 url()
| "url-token"
// 匯入是由 Bun 注入的
| "internal"
// 入口點(不常見)
| "entry-point-build"
| "entry-point-run"
}
const transpiler = new Bun.Transpiler({ loader: "jsx" });