Documentation Index
Fetch the complete documentation index at: https://mintlify.com/zhcndoc/bun/llms.txt
Use this file to discover all available pages before exploring further.
Bun’s bundler can process HTML files as entrypoints, automatically bundling all referenced assets (scripts, stylesheets, images, etc.) and updating the HTML to reference the bundled files.
Basic usage
Given an HTML file:
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./app.ts"></script>
</body>
</html>
Bundle it with:
bun build ./index.html --outdir ./dist
The output will be:
dist/
index.html
app-[hash].js
styles-[hash].css
And the HTML will be updated to reference the hashed files:
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" href="./styles-a1b2c3.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./app-d4e5f6.js"></script>
</body>
</html>
Supported elements
Bun’s HTML processor recognizes and bundles the following elements:
Scripts
<!-- Module scripts are bundled -->
<script type="module" src="./app.ts"></script>
<!-- Regular scripts are also bundled -->
<script src="./legacy.js"></script>
<!-- Inline scripts are preserved -->
<script>
console.log("Hello!");
</script>
Stylesheets
<!-- CSS files are bundled -->
<link rel="stylesheet" href="./styles.css" />
<!-- Multiple stylesheets are merged -->
<link rel="stylesheet" href="./reset.css" />
<link rel="stylesheet" href="./theme.css" />
Images
<!-- Images are hashed and copied -->
<img src="./logo.png" alt="Logo" />
<!-- srcset is also processed -->
<img
src="./hero.jpg"
srcset="./hero-1x.jpg 1x, ./hero-2x.jpg 2x"
alt="Hero"
/>
Other assets
<!-- Favicons -->
<link rel="icon" href="./favicon.ico" />
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
<!-- Fonts -->
<link
rel="preload"
href="./font.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<!-- Manifests -->
<link rel="manifest" href="./manifest.json" />
<!-- Video and audio -->
<video src="./video.mp4" />
<audio src="./audio.mp3" />
External URLs
External URLs (those starting with http://, https://, or //) are preserved as-is:
<!-- These are NOT bundled -->
<script src="https://cdn.example.com/library.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter" />
<img src="https://example.com/remote-image.jpg" />
Public path
Use --public-path to prefix all asset URLs:
bun build ./index.html --outdir ./dist --public-path /assets/
<script type="module" src="/assets/app-d4e5f6.js"></script>
<link rel="stylesheet" href="/assets/styles-a1b2c3.css" />
This is useful for CDN deployments:
bun build ./index.html --outdir ./dist --public-path https://cdn.example.com/
Minification
HTML is minified when --minify is enabled:
bun build ./index.html --outdir ./dist --minify
This removes:
- Whitespace between elements
- HTML comments (except conditional comments)
- Unnecessary quotes around attribute values
- Optional closing tags
Multiple HTML files
You can bundle multiple HTML files:
bun build ./index.html ./about.html ./contact.html --outdir ./dist
Each HTML file becomes an independent entrypoint with its own set of bundled assets.
Code splitting
When multiple HTML files share JavaScript or CSS, those assets can be code-split:
bun build ./index.html ./about.html --outdir ./dist --splitting
Shared code is extracted into separate chunk files, and each HTML file references the appropriate chunks.
JavaScript API
await Bun.build({
entrypoints: ["./index.html"],
outdir: "./dist",
minify: true,
publicPath: "/assets/",
});
Dynamic HTML generation
For server-side rendering or dynamic HTML generation, import HTML files in your JavaScript:
import html from "./index.html";
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response(html, {
headers: { "Content-Type": "text/html" },
});
},
});
When bundled with --target=bun, the HTML import resolves to a manifest object for serving pre-bundled assets efficiently.
Full-stack applications
Combine HTML processing with server-side code:
import html from "./index.html";
const server = Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url);
// Serve the HTML for the root path
if (url.pathname === "/") {
return new Response(html, {
headers: { "Content-Type": "text/html" },
});
}
// API routes
if (url.pathname === "/api/data") {
return Response.json({ message: "Hello!" });
}
return new Response("Not found", { status: 404 });
},
});
console.log(`Server running at http://localhost:${server.port}`);
Build for production:
bun build ./server.ts --outdir ./dist --target=bun --compile
This creates a standalone executable with all assets embedded.
Templates and components
For more complex HTML generation, use template literals or JSX:
function Layout({ children }: { children: any }) {
return (
<html>
<head>
<title>My App</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div id="root">{children}</div>
<script type="module" src="./app.ts" />
</body>
</html>
);
}
const server = Bun.serve({
port: 3000,
fetch(req) {
const html = (
<Layout>
<h1>Welcome!</h1>
</Layout>
);
return new Response(html, {
headers: { "Content-Type": "text/html" },
});
},
});
Asset hashing
All bundled assets are content-hashed by default:
app-a1b2c3d4.js
styles-e5f6g7h8.css
logo-i9j0k1l2.png
This enables:
- Long-term caching (files can be cached forever)
- Cache invalidation (changing content changes the hash)
- Parallel loading (no version conflicts)
Source maps
Generate source maps for JavaScript bundles:
bun build ./index.html --outdir ./dist --sourcemap=external
Source map files are placed alongside their corresponding bundles:
dist/
index.html
app-a1b2c3.js
app-a1b2c3.js.map
Examples
Static site
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Static Site</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<header>
<img src="./logo.svg" alt="Logo" />
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main id="content"></main>
<script type="module" src="./app.ts"></script>
</body>
</html>
bun build ./index.html --outdir ./dist --minify
Single-page application
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>SPA</title>
<link rel="stylesheet" href="./src/styles/main.css" />
</head>
<body>
<div id="app"></div>
<script type="module" src="./src/main.tsx"></script>
</body>
</html>
import { render } from "react-dom";
import { App } from "./App";
render(<App />, document.getElementById("app"));
bun build ./index.html --outdir ./dist --minify --splitting
Progressive Web App
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PWA</title>
<link rel="manifest" href="./manifest.json" />
<link rel="icon" href="./favicon.ico" />
<link rel="apple-touch-icon" href="./icon-192.png" />
<meta name="theme-color" content="#000000" />
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./app.ts"></script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js');
}
</script>
</body>
</html>
bun build ./index.html --outdir ./dist --minify --public-path /
Troubleshooting
Paths not resolving
Make sure all asset paths are relative to the HTML file:
<!-- Good -->
<script src="./app.ts"></script>
<img src="./images/logo.png" />
<!-- Bad -->
<script src="app.ts"></script>
<img src="images/logo.png" />
Assets not found
Check that the referenced files exist relative to the HTML file:
project/
index.html
app.ts
images/
logo.png
External URLs bundled
Ensure external URLs start with http://, https://, or //:
<!-- These are external -->
<script src="https://cdn.example.com/lib.js"></script>
<script src="//cdn.example.com/lib.js"></script>
<!-- This will be bundled -->
<script src="cdn.example.com/lib.js"></script>
Inline scripts interfering
Inline scripts run immediately and might interfere with bundled modules. Use type="module" for modern code:
<!-- Modern approach -->
<script type="module" src="./app.ts"></script>
<!-- Inline module -->
<script type="module">
import { init } from "./app.ts";
init();
</script>