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");Детали">
При вызове .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-поток.
Если ваш код использует макрос, он потенциально создаст новую копию среды выполнения JavaScript Bun в этом новом потоке.
.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 имеет 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 как строified JSON или объект
// Используйте это для установки пользовательской JSX-фабрики, фрагмента или источника импорта
// Например, если вы хотите использовать 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:
// import foo from 'bar'; в JavaScript
| "import-statement"
// require("foo") в JavaScript
| "require-call"
// require.resolve("foo") в JavaScript
| "require-resolve"
// Dynamic import() в JavaScript
| "dynamic-import"
// @import() в CSS
| "import-rule"
// url() в CSS
| "url-token"
// Импорт был внедрен Bun
| "internal"
// Точка входа (не распространено)
| "entry-point-build"
| "entry-point-run"
}
const transpiler = new Bun.Transpiler({ loader: "jsx" });