--- title: "File Types" description: "File types and loaders supported by Bun's bundler and runtime" --- The Bun bundler implements a set of default loaders. As a rule of thumb, the bundler and the runtime support the same set of file types. `.js` `.cjs` `.mjs` `.mts` `.cts` `.ts` `.tsx` `.jsx` `.css` `.json` `.jsonc` `.json5` `.toml` `.yaml` `.yml` `.xml` `.txt` `.text` `.md` `.markdown` `.wasm` `.node` `.html` `.sh` Bun uses the file extension to pick the built-in _loader_ that parses the file. Every loader has a name, such as `js`, `tsx`, or `json`. These names are used when building [plugins](/bundler/plugins) that extend Bun with custom loaders. To specify a loader explicitly, use the `type` import attribute. ```ts import my_toml from "./my_file" with { type: "toml" }; // or with dynamic imports const { default: my_toml } = await import("./my_file", { with: { type: "toml" } }); ``` --- ## Built-in loaders ### `js` **JavaScript**. Default for `.cjs` and `.mjs`. Parses the code and applies a set of default transforms like dead-code elimination and tree shaking. Bun does not down-convert syntax. ### `jsx` **JavaScript + JSX**. Default for `.js` and `.jsx`. Same as the `js` loader, but JSX syntax is supported. By default, Bun down-converts JSX to plain JavaScript; the details depend on the `jsx*` compiler options in your `tsconfig.json`. Refer to the TypeScript documentation [on JSX](https://www.typescriptlang.org/docs/handbook/jsx.html). ### `ts` **TypeScript loader**. Default for `.ts`, `.mts`, and `.cts`. Strips out all TypeScript syntax, then behaves identically to the `js` loader. Bun does not perform typechecking. ### `tsx` **TypeScript + JSX loader**. Default for `.tsx`. Transpiles both TypeScript and JSX to vanilla JavaScript. ### `json` **JSON loader**. Default for `.json`. JSON files can be directly imported. ```ts import pkg from "./package.json"; pkg.name; // => "my-package" ``` During bundling, Bun inlines the parsed JSON into the bundle as a JavaScript object. ```ts var pkg = { name: "my-package", // ... other fields }; pkg.name; ``` If you pass a `.json` file as an entrypoint to the bundler, Bun converts it to a `.js` module that `export default`s the parsed object. ```json Input { "name": "John Doe", "age": 35, "email": "johndoe@example.com" } ``` ```ts Output export default { name: "John Doe", age: 35, email: "johndoe@example.com", }; ``` ### `jsonc` **JSON with Comments loader**. Default for `.jsonc`. JSONC (JSON with Comments) files can be directly imported. Bun parses them, stripping out comments and trailing commas. ```ts import config from "./config.jsonc"; console.log(config); ``` During bundling, Bun inlines the parsed JSONC into the bundle as a JavaScript object, identical to the `json` loader. ```ts var config = { option: "value", }; ``` Bun automatically uses the `jsonc` loader for `tsconfig.json`, `jsconfig.json`, `package.json`, and `bun.lock` files. ### `toml` **TOML loader**. Default for `.toml`. TOML files can be directly imported. Bun parses them with its fast native TOML parser. ```ts import config from "./bunfig.toml"; config.logLevel; // => "debug" // via import attribute: // import myCustomTOML from './my.config' with {type: "toml"}; ``` During bundling, Bun inlines the parsed TOML into the bundle as a JavaScript object. ```ts var config = { logLevel: "debug", // ...other fields }; config.logLevel; ``` If you pass a `.toml` file as an entrypoint, Bun converts it to a `.js` module that `export default`s the parsed object. ```toml Input name = "John Doe" age = 35 email = "johndoe@example.com" ``` ```ts Output export default { name: "John Doe", age: 35, email: "johndoe@example.com", }; ``` ### `yaml` **YAML loader**. Default for `.yaml` and `.yml`. YAML files can be directly imported. Bun parses them with its fast native YAML parser. ```ts import config from "./config.yaml"; console.log(config); // via import attribute: import data from "./data.txt" with { type: "yaml" }; ``` During bundling, Bun inlines the parsed YAML into the bundle as a JavaScript object. ```ts var config = { name: "my-app", version: "1.0.0", // ...other fields }; ``` If you pass a `.yaml` or `.yml` file as an entrypoint, Bun converts it to a `.js` module that `export default`s the parsed object. ```yaml Input name: John Doe age: 35 email: johndoe@example.com ``` ```ts Output export default { name: "John Doe", age: 35, email: "johndoe@example.com", }; ``` ### `json5` **JSON5 loader**. Default for `.json5`. JSON5 files can be directly imported. Bun parses them with its fast native JSON5 parser. JSON5 is a superset of JSON that adds comments, trailing commas, unquoted keys, single-quoted strings, and more. ```ts import config from "./config.json5"; console.log(config); // via import attribute: import data from "./data.txt" with { type: "json5" }; ``` During bundling, Bun inlines the parsed JSON5 into the bundle as a JavaScript object. ```ts var config = { name: "my-app", version: "1.0.0", // ...other fields }; ``` If you pass a `.json5` file as an entrypoint, Bun converts it to a `.js` module that `export default`s the parsed object. ```json5 Input { // Configuration name: "John Doe", age: 35, email: "johndoe@example.com", } ``` ```ts Output export default { name: "John Doe", age: 35, email: "johndoe@example.com", }; ``` ### `xml` **XML loader**. Default for `.xml`. XML files can be directly imported. Bun parses them with its native XML 1.0 parser into the compact object shape of [`Bun.XML.parse`](/runtime/xml): - One key for the root element - `"@name"` keys for attributes - Arrays for repeated child elements - `"#text"` for text next to attributes or children - Every value is a string ```ts import doc from "./config.xml"; console.log(doc.config["@version"]); // via import attribute: import feed from "./export.rss" with { type: "xml" }; ``` During bundling, Bun inlines the parsed XML into the bundle as a JavaScript object. ```ts var doc = { config: { "@version": "2", // ...other fields }, }; ``` If you pass a `.xml` file as an entrypoint, Bun converts it to a `.js` module that `export default`s the parsed object. ```xml Input John Doe johndoe@example.com admin editor ``` ```ts Output export default { user: { "@id": "1", name: "John Doe", email: "johndoe@example.com", role: ["admin", "editor"], }, }; ``` ### `text` **Text loader**. Default for `.txt` and `.text`. Text files can be directly imported. Bun reads the file and returns it as a string. ```ts import contents from "./file.txt"; console.log(contents); // => "Hello, world!" // To import an html file as text // The "type' attribute can be used to override the default loader. import html from "./index.html" with { type: "text" }; ``` When the file is referenced during a build, Bun inlines the contents into the bundle as a string. ```ts var contents = `Hello, world!`; console.log(contents); ``` If you pass a `.txt` file as an entrypoint, Bun converts it to a `.js` module that `export default`s the file contents. ```txt Input Hello, world! ``` ```ts Output export default "Hello, world!"; ``` ### `md` **Markdown loader**. Default for `.md` and `.markdown`. Markdown files can be directly imported. Bun renders the file to HTML and returns the HTML as a string. ```ts import html from "./README.md"; console.log(html); // => "

Title

\n" // via import attribute (`markdown` is an alias of `md`): import notes from "./notes.txt" with { type: "md" }; ``` During bundling, Bun inlines the rendered HTML into the bundle as a string. ### `napi` **Native addon loader**. Default for `.node`. In the runtime, native addons can be directly imported. ```ts import addon from "./addon.node"; console.log(addon); ``` In the bundler, Bun handles `.node` files using the [`file`](#file) loader. ### `sqlite` **SQLite loader**. `with { "type": "sqlite" }` import attribute In the runtime and bundler, SQLite databases can be directly imported. Bun loads the database with [`bun:sqlite`](/runtime/sqlite). ```ts import db from "./my.db" with { type: "sqlite" }; ``` The `sqlite` loader is only supported when the `target` is `bun`. By default, the database is external to the bundle: Bun doesn't bundle the on-disk database file into the final output, so you can use a database loaded elsewhere. You can change this behavior with the `"embed"` attribute: ```ts // embed the database into the bundle import db from "./my.db" with { type: "sqlite", embed: "true" }; ``` With a [standalone executable](/bundler/executables), Bun embeds the database into the single-file executable. Otherwise, the database to embed is copied into the `outdir` with a hashed filename. ### `html` The `html` loader processes HTML files and bundles any referenced assets. It: - Bundles and hashes referenced JavaScript files (` ``` Bun outputs a new HTML file with the bundled assets: ```html dist/output.html Local image External image ``` The loader uses [`lol-html`](https://github.com/cloudflare/lol-html) to extract script and link tags as entrypoints, and other assets as external. The list of selectors is: - `audio[src]` - `img[src]` - `img[srcset]` - `link[as='font'][href], link[type^='font/'][href]` - `link[as='image'][href]` - `link[as='style'][href]` - `link[as='video'][href], link[as='audio'][href]` - `link[as='worker'][href]` - `link[rel='icon'][href], link[rel='apple-touch-icon'][href]` - `link[rel='manifest'][href]` - `link[rel='stylesheet'][href]` - `script[src]` - `source[src]` - `source[srcset]` - `video[poster]` - `video[src]` **HTML Loader Behavior in Different Contexts** The `html` loader behaves differently depending on how it's used: 1. **Static Build:** When you run `bun build ./index.html`, Bun produces a static site with all assets bundled and hashed. 2. **Runtime:** When you run `bun run server.ts` (where `server.ts` imports an HTML file), Bun bundles assets on-the-fly during development, enabling features like hot module replacement. 3. **Full-stack Build:** When you run `bun build --target=bun server.ts` (where `server.ts` imports an HTML file), the import resolves to a manifest object that `Bun.serve` uses to efficiently serve pre-bundled assets in production. ### `css` **CSS loader**. Default for `.css`. CSS files can be directly imported. This is primarily useful when [bundling HTML](/bundler/html-static#importing-css-in-javascript), where CSS is bundled alongside HTML. ```ts import "./styles.css"; ``` The import returns no value; it's only used for its side effects. ### `sh` loader **Bun Shell loader**. Default for `.sh` files This loader parses [Bun Shell](/runtime/shell) scripts. It's only supported when starting Bun itself, so it's not available in the bundler or in the runtime. ```sh bun run ./script.sh ``` ### `file` **File loader**. Default for all unrecognized file types. The file loader resolves the import as a _path/URL_ to the imported file. It's commonly used for referencing media or font assets. ```ts logo.ts import logo from "./logo.svg"; console.log(logo); ``` _In the runtime_, Bun checks that the `logo.svg` file exists and resolves the import to its absolute path on disk. ```bash bun run logo.ts /path/to/project/logo.svg ``` _In the bundler_, Bun copies the file into `outdir` as-is, and the import resolves to a relative path pointing to the copied file. ```ts Output var logo = "./logo.svg"; console.log(logo); ``` If `publicPath` is set, the import uses its value as a prefix to construct an absolute path/URL. | Public path | Resolved import | | ---------------------------- | ---------------------------------- | | `""` (default) | `./logo.svg` | | `"/assets/"` | `/assets/logo.svg` | | `"https://cdn.example.com/"` | `https://cdn.example.com/logo.svg` | The value of [`naming.asset`](/bundler#naming) determines the location and file name of the copied file. If you're using TypeScript, you may get an error like this: ```ts // TypeScript error // Cannot find module './logo.svg' or its corresponding type declarations. ``` To fix this, create a `*.d.ts` file anywhere in your project (any name works) with the following contents: ```ts declare module "*.svg" { const content: string; export default content; } ``` This tells TypeScript to treat any default import from `.svg` as a string.