Bun expone su transpilador interno a través de la clase Bun.Transpiler. Para crear una instancia del transpilador de Bun:
const transpiler = new Bun.Transpiler({
loader: "tsx", // "js" | "jsx" | "ts" | "tsx"
});.transformSync()
Transpila código sincrónicamente con el método .transformSync(). Los módulos no se resuelven y el código no se ejecuta. El resultado es una cadena 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 anular el cargador predeterminado especificado en el constructor new Bun.Transpiler(), pasa un segundo argumento a .transformSync().
transpiler.transformSync("<div>hi!</div>", "tsx");Detalles internos
Cuando se llama a .transformSync, el transpilador se ejecuta en el mismo hilo que el código actualmente ejecutado.
Si se usa una macro, se ejecutará en el mismo hilo que el transpilador, pero en un bucle de eventos separado del resto de tu aplicación. Actualmente, los globales entre macros y código regular se comparten, lo que significa que es posible (pero no recomendado) compartir estados entre macros y código regular. Intentar usar nodos AST fuera de una macro es un comportamiento indefinido.
.transform()
El método transform() es una versión asíncrona de .transformSync() que devuelve un Promise<string>.
const transpiler = new Bun.Transpiler({ loader: "jsx" });
const result = await transpiler.transform("<div>hi!</div>");
console.log(result);A menos que estés transpilando muchos archivos grandes, probablemente deberías usar Bun.Transpiler.transformSync. El costo del threadpool a menudo tomará más tiempo que realmente transpilar código.
await transpiler.transform("<div>hi!</div>", "tsx");Detalles internos
El método .transform() ejecuta el transpilador en el threadpool de workers de Bun, así que si lo ejecutas 100 veces, se ejecutará a través de Math.floor($cpu_count * 0.8) hilos, sin bloquear el hilo principal de JavaScript.
Si tu código usa una macro, potencialmente generará una nueva copia del entorno de tiempo de ejecución de JavaScript de Bun en ese nuevo hilo.
.scan()
La instancia Transpiler también puede escanear código fuente y devolver una lista de sus importaciones y exportaciones, más metadatos adicionales sobre cada uno. Las importaciones y exportaciones solo de tipo se ignoran.
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 importación en el array imports tiene un path y kind. Bun categoriza las importaciones en los siguientes 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 sensible al rendimiento, puedes usar el método .scanImports() para obtener una lista de importaciones. Es más rápido que .scan() (especialmente para archivos grandes) pero marginalmente menos preciso debido a algunas optimizaciones de rendimiento.
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"
}
]Referencia
type Loader = "jsx" | "js" | "ts" | "tsx";
interface TranspilerOptions {
// Reemplazar clave con valor. El valor debe ser una cadena JSON.
// { "process.env.NODE_ENV": "\"production\"" }
define?: Record<string, string>,
// Cargador predeterminado para este transpilador
loader?: Loader,
// Plataforma predeterminada a la que dirigirse
// Esto afecta cómo se usa import y/o require
target?: "browser" | "bun" | "node",
// Especificar un archivo tsconfig.json como JSON en cadena o un objeto
// Usa esto para establecer una fábrica JSX personalizada, fragmento, o fuente de importación
// Por ejemplo, si quieres usar Preact en lugar de React. O si quieres usar Emotion.
tsconfig?: string | TSConfig,
// Reemplazar importaciones con macros
macro?: MacroMap,
// Especificar un conjunto de exportaciones para eliminar
// O renombrar ciertas exportaciones
exports?: {
eliminate?: string[];
replace?: Record<string, string>;
},
// Si eliminar importaciones no usadas del archivo transpilado
// Predeterminado: false
trimUnusedImports?: boolean,
// Si habilitar un conjunto de optimizaciones JSX
// jsxOptimizationInline ...,
// Minificación experimental de espacios en blanco
minifyWhitespace?: boolean,
// Si insertar valores constantes
// Típicamente mejora el rendimiento y disminuye el tamaño del bundle
// Predeterminado: true
inline?: boolean,
}
// Mapear rutas de importación a 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'; en JavaScript
| "import-statement"
// require("foo") en JavaScript
| "require-call"
// require.resolve("foo") en JavaScript
| "require-resolve"
// Dynamic import() en JavaScript
| "dynamic-import"
// @import() en CSS
| "import-rule"
// url() en CSS
| "url-token"
// La importación fue inyectada por Bun
| "internal"
// Punto de entrada (no común)
| "entry-point-build"
| "entry-point-run"
}
const transpiler = new Bun.Transpiler({ loader: "jsx" });