Skip to main content
Bun supports multiple file types through its loader system. Each loader determines how a file is processed and executed.

Built-in Loaders

Bun includes loaders for common file types:

JavaScript & TypeScript

  • .js - JavaScript (js loader)
  • .mjs - ES module JavaScript (js loader)
  • .cjs - CommonJS JavaScript (js loader)
  • .ts - TypeScript (ts loader)
  • .mts - TypeScript ES module (ts loader)
  • .cts - TypeScript CommonJS (ts loader)
  • .jsx - JavaScript with JSX (jsx loader)
  • .tsx - TypeScript with JSX (tsx loader)
  • .json - JSON (json loader)
  • .jsonc - JSON with comments (jsonc loader)
  • .json5 - JSON5 (json5 loader)
  • .toml - TOML (toml loader)
  • .yaml, .yml - YAML (yaml loader)
  • .css - CSS stylesheets (css loader)
  • .html - HTML (html loader)
  • .md - Markdown (md loader)
  • .wasm - WebAssembly (wasm loader)
  • .sqlite, .db - SQLite databases (sqlite loader)
  • .node - Native addons (napi loader)
  • .txt - Plain text (text loader)
  • base64 - Base64 encoding
  • dataurl - Data URL encoding
  • file - Copy file to output directory

Automatic Loader Selection

Bun automatically selects the appropriate loader based on file extension:
Automatic loader selection
// TypeScript - uses 'ts' loader
import { add } from "./math.ts";

// JSX - uses 'jsx' loader  
import Button from "./Button.jsx";

// JSON - uses 'json' loader
import config from "./config.json";

// TOML - uses 'toml' loader
import data from "./data.toml";

// Text - uses 'text' loader
import content from "./README.md" with { type: "text" };

Loader Details

JavaScript Loaders (js, jsx)

Processes JavaScript files with optional JSX transformation:
JS loader features
// Modern JavaScript features
const data = await fetch("/api/data").then(r => r.json());

// Optional chaining & nullish coalescing
const name = user?.profile?.name ?? "Anonymous";

// Top-level await (ESM only)
await database.connect();
Features:
  • No transpilation needed for modern JS
  • JSX transformation when using .jsx extension
  • Source map generation for debugging
  • CommonJS/ESM interoperability

TypeScript Loaders (ts, tsx)

Strips TypeScript types and compiles to JavaScript:
TypeScript loader
// Type annotations removed at runtime
function greet(name: string): string {
  return `Hello, ${name}!`;
}

// Interfaces completely erased
interface User {
  id: number;
  name: string;
}

// Decorators supported (experimental & standard)
@sealed
class Handler {
  @log
  handle() { }
}

// Using declarations (explicit resource management)
using file = openFile("data.txt");
Features:
  • Fast type stripping (no type checking)
  • Decorator support (both legacy and standard)
  • tsconfig.json path mapping
  • Experimental features: decorators, using

JSON Loaders (json, jsonc, json5)

Parses JSON and returns a JavaScript object:
JSON loaders
// Standard JSON
import config from "./config.json";
console.log(config.apiKey);

// JSON with comments (jsonc)
import settings from "./settings.jsonc";

// JSON5 - extended syntax
import data from "./data.json5";
// Supports: trailing commas, comments, unquoted keys
Performance:
  • Uses optimized JSON parser with SIMD
  • Direct object construction (no eval)
  • Type: json loaders return immutable objects

Text Loader

Returns file contents as a string:
Text loader
import readme from "./README.md" with { type: "text" };
import sql from "./query.sql" with { type: "text" };

console.log(readme); // "# My Project\n..."

Base64 & DataURL Loaders

Encode files as base64 or data URLs:
Encoding loaders
// Base64 encoding
import encoded from "./image.png" with { type: "base64" };
// Returns: string (base64 encoded)

// Data URL encoding  
import dataURL from "./image.png" with { type: "dataurl" };
// Returns: "data:image/png;base64,..."
Use cases:
  • Embedding small assets in bundles
  • Inline images in HTML/CSS
  • Data URIs for web APIs

File Loader

Copies files to output directory and returns the path:
File loader
import path from "./logo.png" with { type: "file" };
// Returns: "/logo-a8b3c2d1.png"
Behavior:
  • Copies file to public directory
  • Generates content-hashed filename
  • Returns public path to the file

WASM Loader

Loads WebAssembly modules:
WASM loader
import wasm from "./module.wasm";

// Synchronous instantiation
const { add } = wasm;
console.log(add(5, 3)); // 8

SQLite Loader

Loads SQLite databases:
SQLite loader
import db from "./data.sqlite";

// Query the database
const users = db.query("SELECT * FROM users").all();
Variants:
  • sqlite - External database file
  • sqlite_embedded - Embeds database in binary

NAPI Loader

Loads native Node.js addons:
NAPI loader
import addon from "./native.node";

addon.someNativeFunction();

Configuring Loaders

CLI Flags

Override the loader for specific extensions:
CLI loader configuration
# Treat .js files as JSX
bun --loader .js:jsx app.js

# Load .txt files as JavaScript
bun --loader .txt:js config.txt

# Multiple loaders
bun --loader .data:json --loader .config:toml app.ts

bunfig.toml

Persistent loader configuration:
bunfig.toml
[loader]
".js" = "jsx"          # Treat .js as JSX
".data" = "json"       # Parse .data as JSON  
".config" = "toml"     # Parse .config as TOML
".graphql" = "text"    # Load .graphql as text

Bun.build API

Programmatic loader configuration:
Bun.build loaders
await Bun.build({
  entrypoints: ["./app.ts"],
  loader: {
    ".svg": "text",
    ".png": "dataurl",
    ".woff2": "file",
  },
});

Import Attributes

Explicitly specify loader with import attributes:
Import attributes
// Force text loader for JSON file
import data from "./data.json" with { type: "text" };

// Load as JSON (default for .json)
import config from "./config.json" with { type: "json" };

// Load module as WebAssembly
import wasm from "./module.wasm" with { type: "wasm" };

Loader Implementation

Loaders are implemented in src/options.zig:
Loader enum (src/options.zig:617)
pub const Loader = enum(u8) {
    jsx = 0,
    js = 1,
    ts = 2,
    tsx = 3,
    css = 4,
    file = 5,
    json = 6,
    jsonc = 7,
    toml = 8,
    wasm = 9,
    napi = 10,
    base64 = 11,
    dataurl = 12,
    text = 13,
    bunsh = 14,
    sqlite = 15,
    sqlite_embedded = 16,
    html = 17,
    yaml = 18,
    json5 = 19,
    md = 20,
};

Custom Loaders (Plugins)

Extend Bun with custom loaders using plugins:
Custom loader plugin
import { plugin } from "bun";

plugin({
  name: "yaml-loader",
  setup(build) {
    build.onLoad({ filter: /\.yaml$/ }, async (args) => {
      const text = await Bun.file(args.path).text();
      const data = parseYAML(text);
      return {
        contents: `export default ${JSON.stringify(data)}`,
        loader: "js",
      };
    });
  },
});

Performance Considerations

Loaders execute during import, affecting startup time:
  • Fast: js, ts, json - minimal overhead
  • Medium: jsx, tsx, toml, yaml - requires parsing
  • Slow: Large binary files (wasm, sqlite)

Optimization Tips

  1. Lazy loading: Dynamically import large files
  2. Caching: Bun caches transpiled files automatically
  3. Bundling: Pre-bundle for production to avoid runtime transpilation
Lazy loading example
// Instead of:
import largeModule from "./large.ts";

// Use dynamic import:
const largeModule = await import("./large.ts");
  • TypeScript - TypeScript-specific configuration
  • JSX - JSX transformation options
  • Modules - Module resolution
  • Bundling - Build-time loader configuration

Build docs developers (and LLMs) love