> ## Documentation Index
> Fetch the complete documentation index at: https://bun.ll1025.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# HTML 和静态站点

> 使用 Bun 的打包器构建静态站点、落地页和 Web 应用

Bun 的打包器对 HTML 有一流支持。零配置构建静态站点、落地页和 Web 应用：将 Bun 指向你的 HTML 文件，它会打包文件引用的脚本、样式表和资源。

```html title="index.html" icon="file-code" theme={null}
<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="./styles.css" />
    <script src="./app.ts" type="module"></script>
  </head>
  <body>
    <img src="./logo.png" />
  </body>
</html>
```

首先，将 HTML 文件传递给 `bun`。

```bash terminal icon="terminal" theme={null}
bun ./index.html
```

```
Bun v1.3.3
ready in 6.62ms
→ http://localhost:3000/
Press h + Enter to show shortcuts
```

无需配置，Bun 的开发服务器提供：

* **自动打包** —— 打包并提供你的 HTML、JavaScript 和 CSS
* **多入口支持** —— 处理多个 HTML 入口点和 glob 入口点
* **现代 JavaScript** —— 默认支持 TypeScript 和 JSX
* **智能配置** —— 读取 `tsconfig.json` 的路径、JSX 选项和实验性装饰器
* **插件** —— 插件支持，包括 TailwindCSS
* **ESM 和 CommonJS** —— 在你的 JavaScript、TypeScript 和 JSX 文件中使用 ESM 和 CommonJS
* **CSS 打包和压缩** —— 从 `<link>` 标签和 `@import` 语句打包 CSS
* **资源管理** —— 复制和哈希图片及资源，并重写 JavaScript、CSS 和 HTML 中的资源路径

## 单页应用（SPA）

当你将单个 `.html` 文件传递给 Bun 时，Bun 会将其用作所有路径的回退路由。这适用于使用客户端路由的单页应用：

```bash terminal icon="terminal" theme={null}
bun index.html
```

```
Bun v1.3.3
ready in 6.62ms
→ http://localhost:3000/
Press h + Enter to show shortcuts
```

你的 React 或其他 SPA 无需配置即可工作。像 `/about` 和 `/users/123` 这样的路由会提供同一个 HTML 文件，因此你的客户端路由器处理导航。

```html title="index.html" icon="file-code" theme={null}
<!doctype html>
<html>
  <head>
    <title>我的 SPA</title>
    <script src="./app.tsx" type="module"></script>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
```

## 多页应用（MPA）

有些项目有多个独立的路由或 HTML 文件作为入口点。要支持多个入口点，将它们全部传递给 `bun`：

```bash terminal icon="terminal" theme={null}
bun ./index.html ./about.html
```

```txt theme={null}
Bun v1.3.3
ready in 6.62ms
→ http://localhost:3000/
Routes:
  / ./index.html
  /about ./about.html
Press h + Enter to show shortcuts
```

这会提供：

* `index.html` 在 `/`
* `about.html` 在 `/about`

### Glob 模式

要指定多个文件，使用以 `.html` 结尾的 glob 模式：

```bash terminal icon="terminal" theme={null}
bun ./**/*.html
```

```
Bun v1.3.3
ready in 6.62ms
→ http://localhost:3000/
Routes:
  / ./index.html
  /about ./about.html
Press h + Enter to show shortcuts
```

### 路径规范化

Bun 从所有文件的最长公共前缀中选择基础路径。

```bash terminal icon="terminal" theme={null}
bun ./index.html ./about/index.html ./about/foo/index.html
```

```
Bun v1.3.3
ready in 6.62ms
→ http://localhost:3000/
Routes:
  / ./index.html
  /about ./about/index.html
  /about/foo ./about/foo/index.html
Press h + Enter to show shortcuts
```

## JavaScript、TypeScript 和 JSX

Bun 的转译器原生实现了 JavaScript、TypeScript 和 JSX 支持。参见[加载器](/bundler/loaders)。

<Note>Bun 的转译器在运行时也被使用。</Note>

### ES Modules 和 CommonJS

你可以在 JavaScript、TypeScript 和 JSX 文件中使用 ESM 和 CommonJS。Bun 自动转译和打包它们。

没有预构建或单独的优化步骤。所有操作同时完成。

参见[模块解析](/runtime/module-resolution)。

## CSS

Bun 的 CSS 解析器也是原生实现的（约 70,000 行 Rust 代码）。

它也是一个 CSS 打包器。你可以在 CSS 文件中使用 `@import` 来导入其他 CSS 文件。

例如：

<CodeGroup>
  ```css styles.css icon="file-code" theme={null}
  @import "./abc.css";

  .container {
    background-color: blue;
  }
  ```

  ```css abc.css icon="file-code" theme={null}
  body {
    background-color: red;
  }
  ```
</CodeGroup>

输出：

```css styles.css icon="file-code" theme={null}
body {
  background-color: red;
}

.container {
  background-color: blue;
}
```

### 在 CSS 中引用本地资源

```css styles.css icon="file-code" theme={null}
body {
  background-image: url("./logo.png");
}
```

Bun 将 `./logo.png` 复制到输出目录，并在 CSS 文件中重写路径以包含内容哈希。

```css styles.css icon="file-code" theme={null}
body {
  background-image: url("./logo-[ABC123].png");
}
```

### 在 JavaScript 中导入 CSS

要将 CSS 文件与 JavaScript 文件关联，从 JavaScript 文件中导入它。

```ts app.ts icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import "./styles.css";
import "./more-styles.css";
```

这会生成 `./app.css` 和 `./app.js` 到输出目录。从 JavaScript 导入的所有 CSS 文件都按入口点打包为单个 CSS 文件。如果多个 JavaScript 文件导入同一个 CSS 文件，它在输出 CSS 文件中只包含一次。

## 插件

开发服务器支持插件。

### Tailwind CSS

要使用 TailwindCSS，安装 `bun-plugin-tailwind` 插件：

```bash terminal icon="terminal" theme={null}
# 或任意 npm 客户端
bun install --dev bun-plugin-tailwind
```

然后，将插件添加到你的 `bunfig.toml`：

```toml title="bunfig.toml" icon="settings" theme={null}
[serve.static]
plugins = ["bun-plugin-tailwind"]
```

然后，通过 `<link>` 标签、CSS 中的 `@import` 或 JavaScript 中的导入来引用 TailwindCSS。

<Tabs>
  <Tab title="index.html">
    ```html title="index.html" icon="file-code" theme={null}
    <!-- 在 HTML 中引用 TailwindCSS -->
    <link rel="stylesheet" href="tailwindcss" />
    ```
  </Tab>

  <Tab title="styles.css">
    ```css title="styles.css" icon="file-code" theme={null}
    @import "tailwindcss";
    ```
  </Tab>

  <Tab title="app.ts">
    ```ts title="app.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
    import "tailwindcss";
    ```
  </Tab>
</Tabs>

<Info>只需要其中之一，不需要全部三个。</Info>

## 内联环境变量

Bun 可以在构建时将 JavaScript 和 TypeScript 中的 `process.env.*` 引用替换为实际值。将其用于将 API URL 或功能标志等配置注入前端代码。

### 开发服务器（运行时）

使用 `bun ./index.html` 时内联环境变量，在 `bunfig.toml` 中配置 `env` 选项：

```toml title="bunfig.toml" icon="settings" theme={null}
[serve.static]
env = "PUBLIC_*"  # 仅内联以 PUBLIC_ 开头的环境变量（推荐）
# env = "inline"  # 内联所有环境变量
# env = "disable" # 禁用环境变量替换（默认）
```

<Note>
  这只适用于字面的 `process.env.FOO` 引用，不适用于 `import.meta.env` 或间接访问，如 `const env = process.env; env.FOO`。

  如果环境变量未设置，浏览器中可能会出现 `ReferenceError: process is not defined` 等运行时错误。
</Note>

然后运行开发服务器：

```bash terminal icon="terminal" theme={null}
PUBLIC_API_URL=https://api.example.com bun ./index.html
```

### 构建生产环境

为生产环境构建静态 HTML 时，使用 `env` 选项内联环境变量：

<Tabs>
  <Tab title="CLI">
    ```bash terminal icon="terminal" theme={null}
    # 内联所有环境变量
    bun build ./index.html --outdir=dist --env=inline

    # 仅内联特定前缀的环境变量（推荐）
    bun build ./index.html --outdir=dist --env=PUBLIC_*
    ```
  </Tab>

  <Tab title="API">
    ```ts title="build.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
    // 内联所有环境变量
    await Bun.build({
      entrypoints: ["./index.html"],
      outdir: "./dist",
      env: "inline", // [!code highlight]
    });

    // 仅内联特定前缀的环境变量（推荐）
    await Bun.build({
      entrypoints: ["./index.html"],
      outdir: "./dist",
      env: "PUBLIC_*", // [!code highlight]
    });
    ```
  </Tab>
</Tabs>

### 示例

给定这个源文件：

```ts title="app.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
const apiUrl = process.env.PUBLIC_API_URL;
console.log(`API URL: ${apiUrl}`);
```

并使用 `PUBLIC_API_URL=https://api.example.com` 运行：

```bash terminal icon="terminal" theme={null}
PUBLIC_API_URL=https://api.example.com bun build ./index.html --outdir=dist --env=PUBLIC_*
```

打包后的输出包含：

```js title="dist/app.js" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/javascript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=48bd3119866790424aa113cd09edda91" theme={null}
const apiUrl = "https://api.example.com";
console.log(`API URL: ${apiUrl}`);
```

## 将控制台日志从浏览器回显到终端

Bun 的开发服务器可以将控制台日志从浏览器流式传输到终端。要启用此功能，传递 `--console` CLI 标志。

```bash terminal icon="terminal" theme={null}
bun ./index.html --console
```

```
Bun v1.3.3
ready in 6.62ms
→ http://localhost:3000/
Press h + Enter to show shortcuts
```

每次调用 `console.log` 或 `console.error` 都会广播到启动服务器的终端，因此浏览器错误会显示在你运行服务器的同一位置。这也帮助监视终端输出的 AI agent。

内部地，这重用热模块替换（HMR）的现有 WebSocket 连接来发送日志。

## 在浏览器中编辑文件

Bun 的前端开发服务器支持 Chrome DevTools 中的自动工作区文件夹，因此你可以从浏览器保存对文件的编辑。

## 键盘快捷键

当服务器运行时：

* `o + Enter` —— 在浏览器中打开
* `c + Enter` —— 清除控制台
* `q + Enter`（或 `Ctrl+C`）—— 退出服务器

## 构建生产环境

当你准备好部署时，使用 `bun build` 创建优化后的生产包：

<Tabs>
  <Tab title="CLI">
    ```bash terminal icon="terminal" theme={null}
    bun build ./index.html --minify --outdir=dist
    ```
  </Tab>

  <Tab title="API">
    ```ts title="build.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
    await Bun.build({
      entrypoints: ["./index.html"],
      outdir: "./dist",
      minify: true,
    });
    ```
  </Tab>
</Tabs>

<Warning>
  插件仅通过 `Bun.build` 的 API 或通过 `bunfig.toml` 配合前端开发服务器支持，不支持通过 `bun build` 的 CLI。
</Warning>

### 监视模式

运行 `bun build --watch` 以监视更改并自动重新构建。这对库开发效果很好。

<Info>你从未见过如此快速的监视模式。</Info>

## 插件 API

要获得更多控制，通过 JavaScript API 配置打包器，并使用 Bun 内置的 `HTMLRewriter` 预处理 HTML。

```ts title="build.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
await Bun.build({
  entrypoints: ["./index.html"],
  outdir: "./dist",
  minify: true,

  plugins: [
    {
      // 一个使所有 HTML 标签变为小写的插件
      name: "lowercase-html-plugin",
      setup({ onLoad }) {
        const rewriter = new HTMLRewriter().on("*", {
          element(element) {
            element.tagName = element.tagName.toLowerCase();
          },
          text(element) {
            element.replace(element.text.toLowerCase());
          },
        });

        onLoad({ filter: /\.html$/ }, async args => {
          const html = await Bun.file(args.path).text();

          return {
            // Bun 的打包器会扫描 HTML 中的 <script> 标签、<link rel="stylesheet"> 标签和其他资源
            // 并自动打包它们
            contents: rewriter.transform(html),
            loader: "html",
          };
        });
      },
    },
  ],
});
```

## 哪些内容会被处理？

Bun 自动处理所有常见的 Web 资源：

* **脚本**（`<script src>`）由 Bun 的 JavaScript/TypeScript/JSX 打包器处理
* **样式表**（`<link rel="stylesheet">`）由 Bun 的 CSS 解析器和打包器处理
* **图片**（`<img>`、`<picture>`）被复制并哈希
* **媒体**（`<video>`、`<audio>`、`<source>`）被复制并哈希
* 任何具有指向本地文件的 `href` 属性的 `<link>` 标签都会被重写为新路径，并进行哈希

Bun 相对于你的 HTML 文件解析所有路径，因此你可以自由组织项目结构。

<Warning>
  **这是一个进行中的工作**

  * 需要更多插件
  * 需要更多关于资源处理等方面的配置选项
  * 需要一种配置 CORS、头等的方式

  {/* 如果你想提交 PR，大部分代码在[这里](https://github.com/oven-sh/bun/blob/main/src/runtime/api/bun/html-rewriter.ts)。你甚至可以将该文件复制粘贴到你的项目中作为起点。 */}
</Warning>

## 原理

这是 Bun 对 JavaScript 中 [HTML 导入](/bundler/fullstack) 支持的一个轻量封装。

## 独立 HTML

你可以将整个前端打包成一个**独立的 `.html` 文件**，无需外部依赖，使用 `--compile --target=browser`。所有 JavaScript、CSS 和图片都直接内联到 HTML 中。

```bash terminal icon="terminal" theme={null}
bun build --compile --target=browser ./index.html --outdir=dist
```

在[独立 HTML 文档](/bundler/standalone-html)中了解更多。

## 为你的前端添加后端

要为前端添加后端，使用 `Bun.serve` 的 `routes` 选项。参见[全栈文档](/bundler/fullstack)。
