资源

Nitro 支持三种类型的资源:直接提供给客户端的公共资源、内联到服务器包中的导入文件,以及打包到服务器中以供编程访问的服务器资源。

#公共资源

Nitro 通过 public/ 目录处理资源。

public/ 目录中的所有资源将被自动提供。这意味着您可以直接从浏览器访问它们,无需任何特殊配置。

public/
  image.png     <-- /image.png
  video.mp4     <-- /video.mp4
  robots.txt    <-- /robots.txt

#缓存和请求头

公共资源会自动携带 ETag 和 Last-Modified 响应头,以支持条件请求。当客户端发送 If-None-Match 或 If-Modified-Since 请求头时,Nitro 会返回 304 Not Modified 响应。

对于从非根目录 baseURL(如 /build/)提供的资源,Nitro 会阻止请求穿透到应用处理器。如果请求匹配了公共资源基础路径但文件未找到,将立即返回 404。

#生产环境公共资源

构建 Nitro 应用时,public/ 目录将被复制到 .output/public/,同时会创建一个包含元数据的清单文件并嵌入到服务器包中。

{
  "/image.png": {
    "type": "image/png",
    "etag": "\"4a0c-6utWq0Kbk5OqDmksYCa9XV8irnM\"",
    "mtime": "2023-03-04T21:39:45.086Z",
    "size": 18956
  },
  "/robots.txt": {
    "type": "text/plain; charset=utf-8",
    "etag": "\"8-hMqyDrA8fJ0R904zgEPs3L55Jls\"",
    "mtime": "2023-03-04T21:39:45.086Z",
    "size": 8
  },
  "/video.mp4": {
    "type": "video/mp4",
    "etag": "\"9b943-4UwfQXKUjPCesGPr6J5j7GzNYGU\"",
    "mtime": "2023-03-04T21:39:45.085Z",
    "size": 637251
  }
}

这使得 Nitro 无需扫描目录即可了解公共资源,配合缓存响应头提供高性能。

#自定义公共资源目录

您可以使用 publicAssets 配置选项配置额外的公共资源目录。每个条目支持以下属性:

  • dir -- 目录路径(相对于 rootDir 解析)
  • baseURL -- 用于提供资源的 URL 前缀(默认值:"/")
  • maxAge -- 以秒为单位的缓存 max-age。设置后,将通过路由规则应用 Cache-Control: public, max-age=<value>, immutable 响应头。仅当 fallthrough 为 false 时生效(非根目录的默认值)。
  • fallthrough -- 当资源未找到时,请求是否应继续交由应用处理器处理。顶层(baseURL: "/")目录默认为 true;非根目录默认为 false
  • ignore -- 传入 false 以禁用忽略模式,或传入 glob 模式数组以覆盖全局 ignore 选项
nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  publicAssets: [
    {
      baseURL: "build",
      dir: "public/build",
      maxAge: 3600,
    },
  ],
});

在此示例中,public/build/ 目录下的文件在 /build/ 路径下提供,具有一小时缓存且不会穿透到应用处理器。

#压缩公共资源

Nitro 可以在构建期间生成公共资源的预压缩版本。当客户端发送 Accept-Encoding 请求头时,服务器将提供压缩版本(如果可用)。支持的压缩编码包括 gzip(.gz)、brotli(.br)和 zstd(.zst)。

设置 compressPublicAssets: true 以启用所有编码:

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  compressPublicAssets: true,
});

或选择特定编码:

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  compressPublicAssets: {
    gzip: true,
    brotli: true,
    zstd: false,
  },
});

Note

仅压缩可压缩的 MIME 类型(文本、JavaScript、JSON、XML、WASM、字体、SVG 等)且文件大小至少为 1 KB 的文件。源映射文件(.map)会被排除。zstd 压缩要求在构建时使用 Node.js 22+(zlib.zstdCompress),在较旧版本上会被静默跳过

#导入文件

任何文件都可以通过 type import 属性导入。其内容会以内联形式添加到服务器包中,可以作为带有 type: "bytes" 的 Uint8Array,也可以作为带有 type: "text" 的 UTF-8 string:

routes/logo.ts
import { defineHandler } from "nitro";

import logo from "./logo.png" with { type: "bytes" }; // Uint8Array
import readme from "./README.md" with { type: "text" }; // string

export default defineHandler(() => {
  return new Response(logo, { headers: { "content-type": "image/png" } });
});

文件类型会被忽略:任何文件都可以作为字节或文本导入。

动态导入同样受支持:

const { default: logo } = await import("./logo.png", { with: { type: "bytes" } });

或者,raw: 前缀会将文件作为 string(对于文本文件,根据文件类型确定)或 Uint8Array(对于二进制文件)导入:

import readme from "raw:./README.md"; // string
import logo from "raw:./logo.png"; // Uint8Array

Note

导入的文件会以内联形式添加到服务器包中(二进制文件会进行 base64 编码)。对于较大的文件,建议使用服务器资源

Note

TypeScript 尚不支持 bytes 和 text 属性。在此之前,导入未知文件类型时需要添加 // @ts-ignore 注释

#服务器资源

assets/ 目录中的所有资源(如果设置了 serverDir,则相对于该目录,否则相对于项目根目录)都会添加到服务器包中。构建应用后,可以在 .output/server/chunks/raw/ 目录中找到这些资源。请注意资源大小,因为它们会与服务器包一起打包。

Tip

如果您的代码从未使用 useKV(),服务器资源将不会包含在服务器包中。

它们可以通过 assets:server 挂载点使用存储层来访问。

例如,您可以将 json 文件存储在 assets/data.json 中,并在处理器中检索它:

import { defineHandler } from "nitro";
import { useKV } from "nitro/kv";

export default defineHandler(async () => {
  const data = await useKV("assets:server").get("data.json");

  return data;
});

#自定义服务器资源

为了从自定义目录添加资源,您需要在 nitro 配置中定义路径。这允许您从 assets/ 目录之外的目录添加资源。

serverAssets 中的每个条目支持以下属性:

  • baseName -- 用作存储挂载点的名称(通过 assets:<baseName> 访问)
  • dir -- 目录路径(相对于 rootDir 解析)
  • pattern -- 文件包含的 glob 模式(默认:"**/*")
  • ignore -- 用于排除文件的 glob 模式数组
nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  serverAssets: [
    {
      baseName: "templates",
      dir: "./templates",
    },
  ],
});

然后您可以使用 assets:templates 基础路径来检索您的资源。

handlers/success.ts
import { defineHandler } from "nitro";
import { useKV } from "nitro/kv";

export default defineHandler(async (event) => {
  const html = await useKV("assets:templates").get("success.html");

  return html;
});

Note

在开发期间,服务器资源会使用 fs unstorage 驱动程序直接从文件系统读取。在生产环境中,它们会作为带有预计算元数据(MIME 类型、ETag、修改时间)的延迟导入打包到服务器中

Read more in Docs > Storage.