Skip to content

Bun 通過 Bun.Transpiler 類公開其內部轉譯器。要創建 Bun 轉譯器的實例:

ts
const transpiler = new Bun.Transpiler({
  loader: "tsx", // "js | "jsx" | "ts" | "tsx"
});

.transformSync()

使用 .transformSync() 方法同步轉譯代碼。模塊不被解析,代碼不執行。結果是純 JavaScript 代碼字符串。

ts
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);
ts
import { __require as require } from "bun:wrap";
import * as JSX from "react/jsx-dev-runtime";
var jsx = require(JSX).jsxDEV;

export default jsx(
  "div",
  {
    children: "hi!",
  },
  undefined,
  false,
  undefined,
  this,
);

要覆蓋 new Bun.Transpiler() 構造函數中指定的默認加載器,傳遞第二個參數給 .transformSync()

ts
transpiler.transformSync("<div>hi!</div>", "tsx");

細節">

當調用 .transformSync 時,轉譯器在與當前執行代碼相同的線程中運行。

如果使用宏,它將在與轉譯器相同的線程中運行,但在與應用程序其余部分 separate 的事件循環中。目前,宏和常規代碼之間的全局變量是共享的,這意味著可以在宏和常規代碼之間共享狀態(但不推薦)。嘗試在宏之外使用 AST 節點是未定義行為。


.transform()

transform() 方法是 .transformSync() 的異步版本,返回 Promise<string>

js
const transpiler = new Bun.Transpiler({ loader: "jsx" });
const result = await transpiler.transform("<div>hi!</div>");
console.log(result);

除非你轉譯_很多_大文件,否則你可能應該使用 Bun.Transpiler.transformSync。線程池的開銷通常比實際轉譯代碼花費的時間更長。

ts
await transpiler.transform("<div>hi!</div>", "tsx");

細節">

.transform() 方法在 Bun 的工作線程池中運行轉譯器,所以如果你運行它 100 次,它將在 Math.floor($cpu_count * 0.8) 個線程上運行,而不會阻塞主 JavaScript 線程。

如果你的代碼使用宏,它可能會在那個新線程中生成 Bun 的 JavaScript 運行環境的新副本。

.scan()

Transpiler 實例還可以掃描一些源代碼並返回其導入和導出的列表,以及每個導入和導出的額外元數據。僅類型 導入和導出被忽略。

ts
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);
json
{
  "exports": ["name"],
  "imports": [
    {
      "kind": "import-statement",
      "path": "react"
    },
    {
      "kind": "import-statement",
      "path": "remix"
    },
    {
      "kind": "dynamic-import",
      "path": "./loader"
    }
  ]
}

imports 數組中的每個導入都有 pathkind。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() 更快(特別是對於大文件),但由於一些性能優化,准確性略低。

ts
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);
json
[
  {
    "kind": "import-statement",
    "path": "react"
  },
  {
    "kind": "require-call",
    "path": "./cjs.js"
  },
  {
    "kind": "dynamic-import",
    "path": "./loader"
  }
]

參考

ts
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 factory、fragment 或 import source
  // 例如,如果你想使用 Preact 而不是 React。或者如果你想使用 Emotion。
  tsconfig?: string | TSConfig,

  // 用宏替換導入
  macro?: MacroMap,

  // 指定要消除的導出集
  // 或重命名某些導出
  exports?: {
      eliminate?: string[];
      replace?: Record<string, string>;
  },

  // 是否從轉譯文件中移除未使用的導入
  // 默認:false
  trimUnusedImports?: boolean,

  // 是否啟用一組 JSX 優化
  // jsxOptimizationInline ...,

  // 實驗性空格最小化
  minifyWhitespace?: boolean,

  // 是否內聯常量值
  // 通常提高性能並減小包大小
  // 默認:true
  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" });

Bun學習網由www.bunjs.com.cn整理維護