O Bun expõe seu transpiler interno através da classe Bun.Transpiler. Para criar uma instância do transpiler do Bun:
const transpiler = new Bun.Transpiler({
loader: "tsx", // "js | "jsx" | "ts" | "tsx"
});.transformSync()
Transpile código sincronamente com o método .transformSync(). Módulos não são resolvidos e o código não é executado. O resultado é uma string de código JavaScript vanilla.
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,
);Para sobrescrever o loader padrão especificado no construtor new Bun.Transpiler(), passe um segundo argumento para .transformSync().
transpiler.transformSync("<div>hi!</div>", "tsx");Detalhes">
Quando .transformSync é chamado, o transpiler é executado na mesma thread que o código atualmente executado.
Se uma macro for usada, ela será executada na mesma thread que o transpiler, mas em um event loop separado do resto da sua aplicação. Atualmente, globals entre macros e código regular são compartilhados, o que significa que é possível (mas não recomendado) compartilhar estados entre macros e código regular. Tentar usar nós AST fora de uma macro é comportamento indefinido.
.transform()
O método transform() é uma versão assíncrona do .transformSync() que retorna uma Promise<string>.
const transpiler = new Bun.Transpiler({ loader: "jsx" });
const result = await transpiler.transform("<div>hi!</div>");
console.log(result);A menos que você esteja transpilando muitos arquivos grandes, você provavelmente deve usar Bun.Transpiler.transformSync. O custo do threadpool frequentemente levará mais tempo que realmente transpilar o código.
await transpiler.transform("<div>hi!</div>", "tsx");Detalhes">
O método .transform() executa o transpiler no threadpool de workers do Bun, então se você executá-lo 100 vezes, ele será executado através de Math.floor($cpu_count * 0.8) threads, sem bloquear a thread JavaScript principal.
Se seu código usar uma macro, ele potencialmente spawnará uma nova cópia do ambiente de runtime JavaScript do Bun naquela nova thread.
.scan()
A instância Transpiler também pode escanear algum código fonte e retornar uma lista de seus imports e exports, mais metadados adicionais sobre cada um. Imports e exports somente de tipo são ignorados.
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"
}
]
}Cada import no array imports tem um path e kind. O Bun categoriza imports nos seguintes tipos:
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()
Para código sensível a performance, você pode usar o método .scanImports() para obter uma lista de imports. É mais rápido que .scan() (especialmente para arquivos grandes) mas marginalmente menos preciso devido a algumas otimizações de performance.
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"
}
]Referência
type Loader = "jsx" | "js" | "ts" | "tsx";
interface TranspilerOptions {
// Substitui key por value. Value deve ser uma string JSON.
// { "process.env.NODE_ENV": "\"production\"" }
define?: Record<string, string>,
// Loader padrão para este transpiler
loader?: Loader,
// Plataforma padrão para target
// Isso afeta como import e/ou require é usado
target?: "browser" | "bun" | "node",
// Especifica um arquivo tsconfig.json como JSON stringificado ou um objeto
// Use isso para definir uma factory JSX customizada, fragment, ou import source
// Por exemplo, se você quer usar Preact em vez de React. Ou se quer usar Emotion.
tsconfig?: string | TSConfig,
// Substitui imports com macros
macro?: MacroMap,
// Especifica um conjunto de exports para eliminar
// Ou renomear certos exports
exports?: {
eliminate?: string[];
replace?: Record<string, string>;
},
// Se deve remover imports não utilizados do arquivo transpilado
// Padrão: false
trimUnusedImports?: boolean,
// Se deve habilitar um conjunto de otimizações JSX
// jsxOptimizationInline ...,
// Minificação de whitespace experimental
minifyWhitespace?: boolean,
// Se deve inline valores constantes
// Tipicamente melhora performance e diminui tamanho do bundle
// Padrão: true
inline?: boolean,
}
// Mapeia import paths para 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'; em JavaScript
| "import-statement"
// require("foo") em JavaScript
| "require-call"
// require.resolve("foo") em JavaScript
| "require-resolve"
// Dynamic import() em JavaScript
| "dynamic-import"
// @import() em CSS
| "import-rule"
// url() em CSS
| "url-token"
// O import foi injetado pelo Bun
| "internal"
// Entry point (não comum)
| "entry-point-build"
| "entry-point-run"
}
const transpiler = new Bun.Transpiler({ loader: "jsx" });