Nitro Renderer

使用 renderer 通过自定义 HTML 或模板系统处理所有未匹配的路由。
Nitro v3 Alpha 文档仍在开发中——可能会有更新、不完善的地方和偶尔的不准确信息。

renderer 是 Nitro 中的一个特殊 handler,它捕获所有不匹配任何特定 API 或 route handler 的路由。它通常用于服务器端渲染(SSR)、提供单页应用(SPA)或创建自定义 HTML 响应。

HTML 模板

自动检测的 index.html

默认情况下,Nitro 会自动在项目 src 目录中查找 index.html 文件。

如果找到,Nitro 将使用它作为 renderer 模板,并为所有未匹配的路由提供服务。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>我的 Vite + Nitro 应用</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
当检测到 index.html 时,Nitro 会在终端中自动记录:Using index.html as renderer template.

使用此设置:

  • /api/hello → 由你的 API routes 处理
  • /about/contact 等 → 使用 index.html 提供服务

自定义 HTML 文件

你可以使用 Nitro 配置中的 renderer.template 选项指定自定义 HTML 模板文件。

import { defineNitroConfig } from "nitro/config";

export default defineNitroConfig({
  renderer: {
    template: './app.html'
  }
})

超文本预处理器(实验性)

Nitro 使用 rendu 超文本预处理器,它提供了一种简单而强大的方式来创建带有 JavaScript 表达式的动态 HTML 模板。

你可以使用特殊的分隔符来注入动态内容:

  • {{ content }} 输出 HTML 转义的内容
  • {{{ content }}}<?= expression ?> 输出原始(未转义)内容
  • <? ... ?> 用于 JavaScript 控制流

它还暴露了全局变量:

  • $REQUEST:传入的 Request 对象
  • $METHOD:HTTP 方法(GET、POST 等)
  • $URL:请求 URL 对象
  • $HEADERS:请求头
  • $RESPONSE:响应配置对象
  • $COOKIES:包含请求 cookies 的只读对象
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>动态模板</title>
  </head>
  <body>
    <h1>Hello {{ $REQUEST.url }}</h1>
  </body>
</html>
Read more in Rendu 文档.

自定义 renderer handler

对于更复杂的场景,你可以创建自定义 renderer handler,以编程方式生成响应。

创建 renderer 文件并使用 defineRenderHandler 定义自定义渲染逻辑:

renderer.ts
import { defineRenderHandler } from "nitro/runtime";

export default defineRenderHandler((event) => {
  return {
    body: `<!DOCTYPE html>
      <html>
        <head>
          <title>自定义 Renderer</title>
        </head>
        <body>
          <h1>来自自定义 renderer 的问候!</h1>
          <p>当前路径:${event.path}</p>
        </body>
      </html>`,
    headers: {
      'content-type': 'text/html; charset=utf-8'
    }
  }
})

然后,在 Nitro 配置中指定 renderer 入口:

nitro.config.ts
import { defineNitroConfig } from "nitro/config";

export default defineNitroConfig({
  renderer: {
    entry: './renderer.ts'
  }
})

Renderer 优先级

renderer 始终作为 catch-all 路由(/**)并具有最低优先级。这意味着:

首先匹配特定的 API routes(例如 /api/users

接下来匹配特定的 server routes(例如 /about

renderer 捕获其他所有内容

api/
  users.ts        → /api/users (首先匹配)
routes/
  about.ts        → /about (其次匹配)
renderer.ts         → /** (捕获所有其他路由)
如果你在 routes 中定义了 catch-all 路由([...].ts),Nitro 会警告你 renderer 将覆盖它。使用更具体的路由或不同的 HTTP 方法来避免冲突。
Read more in 架构 > 请求生命周期.

使用场景

单页应用(SPA)

为所有路由提供你的 SPA 的 index.html 以启用客户端路由:

这是 Nitro 与 Vite 一起使用时的默认行为。