Bun

轉譯器

Bun 透過 Bun.Transpiler 類別公開其內部轉譯器。若要建立 Bun 轉譯器的執行個體

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 { __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()

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

細節

.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");

細節

.scan()

Transpiler 執行個體也可以掃描一些原始碼,並傳回其匯入和匯出的清單,以及每個匯入和匯出的其他元資料。 僅類型 的匯入和匯出會被忽略。

範例
輸出
範例
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": "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() 方法來取得 import 清單。它比 .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 {
  // Replace key with value. Value must be a JSON string.
  // { "process.env.NODE_ENV": "\"production\"" }
  define?: Record<string, string>,

  // Default loader for this transpiler
  loader?: Loader,

  // Default platform to target
  // This affects how import and/or require is used
  target?: "browser" | "bun" | "node",

  // Specify a tsconfig.json file as stringified JSON or an object
  // Use this to set a custom JSX factory, fragment, or import source
  // For example, if you want to use Preact instead of React. Or if you want to use Emotion.
  tsconfig?: string | TSConfig,

  // Replace imports with macros
  macro?: MacroMap,

  // Specify a set of exports to eliminate
  // Or rename certain exports
  exports?: {
      eliminate?: string[];
      replace?: Record<string, string>;
  },

  // Whether to remove unused imports from transpiled file
  // Default: false
  trimUnusedImports?: boolean,

  // Whether to enable a set of JSX optimizations
  // jsxOptimizationInline ...,

  // Experimental whitespace minification
  minifyWhitespace?: boolean,

  // Whether to inline constant values
  // Typically improves performance and decreases bundle size
  // Default: true
  inline?: boolean,
}

// Map import paths to macros
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:
  // import foo from 'bar'; in JavaScript
  | "import-statement"
  // require("foo") in JavaScript
  | "require-call"
  // require.resolve("foo") in JavaScript
  | "require-resolve"
  // Dynamic import() in JavaScript
  | "dynamic-import"
  // @import() in CSS
  | "import-rule"
  // url() in CSS
  | "url-token"
  // The import was injected by Bun
  | "internal" 
  // Entry point (not common)
  | "entry-point"
}

const transpiler = new Bun.Transpiler({ loader: "jsx" });