Skip to main content
Bun uses the file extension to select a built-in loader that parses and transforms each file. As a rule of thumb, the runtime and bundler support the same set of file types out of the box. Supported extensions: .js .cjs .mjs .mts .cts .ts .tsx .jsx .css .json .jsonc .json5 .toml .yaml .yml .txt .wasm .node .html .sh You can explicitly override the loader for any import using the with { type: "..." } import attribute:
import config from "./my_file" with { type: "toml" };

// Dynamic import
const { default: config } = await import("./my_file", { with: { type: "toml" } });

JavaScript and TypeScript

js loader

Default for .cjs and .mjs. Parses JavaScript and applies default transforms like dead-code elimination and tree shaking. Bun does not down-convert syntax.

jsx loader

Default for .js and .jsx. Same as js, but JSX syntax is supported and transpiled to plain JavaScript. The JSX transform is controlled by jsx* fields in tsconfig.json.

ts loader

Default for .ts, .mts, and .cts. Strips TypeScript syntax, then behaves identically to the js loader. Bun does not perform type checking.

tsx loader

Default for .tsx. Transpiles both TypeScript and JSX to vanilla JavaScript.
All four loaders can be used with require() as well as import. You can require a .ts or .tsx file from a CommonJS module.

Data formats

JSON

Default for .json. JSON files can be imported directly:
import pkg from "./package.json";
pkg.name; // "my-package"
During bundling, the parsed JSON is inlined as a JavaScript object:
var pkg = {
  name: "my-package",
  // ...other fields
};
If a .json file is passed as a bundler entrypoint, it is converted to a .js module that export defaults the parsed object.
{
  "name": "John Doe",
  "age": 35,
  "email": "johndoe@example.com"
}

JSONC

Default for .jsonc. JSONC (JSON with Comments) files can be imported directly. Bun strips comments and trailing commas during parsing.
import config from "./config.jsonc";
console.log(config);
Bun automatically uses the jsonc loader for tsconfig.json, jsconfig.json, package.json, and bun.lock.

TOML

Default for .toml. TOML files can be imported directly using Bun’s fast native TOML parser:
import config from "./bunfig.toml";
config.logLevel; // "debug"
During bundling, the parsed TOML is inlined as a JavaScript object:
var config = {
  logLevel: "debug",
};
If a .toml file is passed as a bundler entrypoint, it becomes a .js module that export defaults the parsed object.
name = "John Doe"
age = 35
email = "johndoe@example.com"

YAML

Default for .yaml and .yml. YAML files can be imported directly using Bun’s native YAML parser:
import config from "./config.yaml";
console.log(config);
You can also use the import attribute to force YAML parsing on any file:
import data from "./data.txt" with { type: "yaml" };

JSON5

Default for .json5. JSON5 is a superset of JSON that supports comments, trailing commas, unquoted keys, and single-quoted strings:
import config from "./config.json5";
console.log(config);
{
  // Configuration
  name: "John Doe",
  age: 35,
  email: "johndoe@example.com",
}

Text and static files

text loader

Default for .txt. The file contents are imported as a string:
import contents from "./file.txt";
console.log(contents); // "Hello, world!"
To import an HTML file as raw text (overriding the default HTML loader):
import html from "./index.html" with { type: "text" };
During bundling, the string is inlined:
var contents = `Hello, world!`;
If a .txt file is passed as a bundler entrypoint, it becomes a .js module that export defaults the string.

file loader

Default for all unrecognized file types. The import resolves to a path or URL pointing to the file. Commonly used for media and font assets:
import logo from "./logo.svg";
console.log(logo); // "/path/to/project/logo.svg"
In the bundler, the file is copied to outdir and the import resolves to a relative path. If publicPath is configured, it is used as a prefix:
Public pathResolved import
"" (default)/logo.svg
"/assets"/assets/logo.svg
"https://cdn.example.com/"https://cdn.example.com/logo.svg

Special loaders

html loader

Default for .html. Processes HTML files and bundles all referenced assets:
  • Bundles and hashes referenced JavaScript (<script src="...">)
  • Bundles and hashes referenced CSS (<link rel="stylesheet" href="...">)
  • Hashes referenced images (<img src="...">)
  • Preserves external URLs (http:// and https://)
<!DOCTYPE html>
<html>
  <body>
    <img src="./image.jpg" alt="Local image" />
    <img src="https://example.com/image.jpg" alt="External image" />
    <script type="module" src="./script.js"></script>
  </body>
</html>
The html loader behaves differently depending on context:
  • Static build (bun build ./index.html): produces a static site with bundled and hashed assets.
  • Runtime (bun run server.ts importing an HTML file): bundles assets on the fly during development with hot module replacement.
  • Full-stack build (bun build --target=bun server.ts): the import resolves to a manifest object that Bun.serve uses to serve pre-bundled assets in production.

css loader

Default for .css. CSS files can be imported directly. No value is returned from the import — it is used for side effects only, primarily in full-stack applications:
import "./styles.css";

napi loader

Default for .node. Native Node.js addons can be imported directly at runtime:
import addon from "./addon.node";
console.log(addon);
In the bundler, .node files are handled by the file loader.

sqlite loader

Triggered by the with { type: "sqlite" } import attribute. Imports an SQLite database directly using bun:sqlite:
import db from "./my.db" with { type: "sqlite" };
To embed the database into a standalone executable:
import db from "./my.db" with { type: "sqlite", embed: "true" };
This loader is only supported when target is bun.

sh loader

Default for .sh files. Executes Bun Shell scripts. Only available at runtime (not in the bundler):
bun run ./script.sh

Build docs developers (and LLMs) love