KV 存储
Nitro 提供了一个内置的存储层,可以抽象文件系统、数据库或任何其他数据源。
Nitro 内置了与 unstorage 的集成,以提供一个运行时无关的持久化层。
用法
要使用存储层,你可以使用 useStorage() 工具函数来访问存储实例。
import { useStorage } from "nitro/storage";
// 默认存储(内存中)
await useStorage().setItem("test:foo", { hello: "world" });
const value = await useStorage().getItem("test:foo");
// 你可以使用 useStorage(base) 指定基础前缀
const testStorage = useStorage("test");
await testStorage.setItem("foo", { hello: "world" });
await testStorage.getItem("foo"); // { hello: "world" }
// 你可以使用泛型来指定返回值类型
await useStorage<{ hello: string }>("test").getItem("foo");
await useStorage("test").getItem<{ hello: string }>("foo");
可用方法
useStorage() 返回的存储实例提供以下方法:
| 方法 | 描述 |
|---|---|
getItem(key) | 获取键的值。如果键不存在则返回 null。 |
getItems(items) | 一次获取多个项目。接受键数组或 { key, options } 对象。 |
getItemRaw(key) | 获取键的原始值,不进行解析。适用于二进制数据。 |
setItem(key, value) | 设置键的值。 |
setItems(items) | 一次设置多个项目。接受 { key, value } 对象数组。 |
setItemRaw(key, value) | 设置键的原始值,不进行序列化。 |
hasItem(key) | 检查键是否存在。返回布尔值。 |
removeItem(key) | 从存储中移除键。 |
getKeys(base?) | 获取所有键,可选按基础前缀过滤。 |
clear(base?) | 清除所有键,可选按基础前缀过滤。 |
getMeta(key) | 获取键的元数据(例如 mtime、atime、ttl)。 |
setMeta(key, meta) | 设置键的元数据。 |
removeMeta(key) | 移除键的元数据。 |
mount(base, driver) | 在基础路径动态挂载存储驱动。 |
unmount(base) | 从基础路径卸载存储驱动。 |
watch(callback) | 监视变更。回调接收 (event, key),其中 event 为 "update" 或 "remove"。 |
unwatch() | 停止监视变更。 |
还提供了简写别名:get、set、has、del、remove、keys。
import { useStorage } from "nitro/storage";
// 获取前缀下的所有键
const keys = await useStorage("test").getKeys();
// 检查键是否存在
const exists = await useStorage().hasItem("test:foo");
// 移除键
await useStorage().removeItem("test:foo");
// 获取原始二进制数据
const raw = await useStorage().getItemRaw("assets/server:image.png");
// 获取元数据(类型、etag、mtime 等)
const meta = await useStorage("assets/server").getMeta("file.txt");
配置
你可以使用 storage 选项挂载一个或多个自定义存储驱动。
键是挂载点名称,值是驱动名称和配置。
nitro.config.ts
import { defineNitroConfig } from "nitro/config";
export default defineNitroConfig({
storage: {
redis: {
driver: "redis",
/* redis 连接器选项 */
}
}
})
然后,你可以使用 useStorage("redis") 函数来使用 redis 存储。
你可以在 unstorage 文档 上找到驱动列表及其配置。
开发存储
你可以使用 devStorage 选项在开发和预渲染期间覆盖存储配置。
当你的生产驱动在开发环境中不可用时(例如托管的 Redis 实例),这很有用。
nitro.config.ts
import { defineNitroConfig } from "nitro/config";
export default defineNitroConfig({
storage: {
db: {
driver: "redis",
host: "prod.example.com",
}
},
devStorage: {
db: {
driver: "fs",
base: "./.data/db"
}
}
})
在开发模式下运行时,devStorage 挂载会合并到 storage 挂载之上,允许你在开发时使用本地文件系统驱动或内存驱动。
内置挂载点
Nitro 自动挂载以下存储路径:
/assets
服务器资源挂载在 /assets 基础路径。此挂载点提供对打包服务器资源的只读访问(参见服务器资源)。
import { useStorage } from "nitro/storage";
// 通过 /assets 挂载点访问服务器资源
const content = await useStorage("assets/server").getItem("my-file.txt");
默认(内存中)
根存储(无基础路径)默认使用内存驱动。此处存储的数据在重启后不会持久化。
import { useStorage } from "nitro/storage";
// 默认为内存存储,不会持久化
await useStorage().setItem("counter", 1);
要持久化数据,请使用 storage 配置选项挂载具有持久后端的驱动(例如 fs、redis 等)。
服务器资源
Nitro 允许你从项目根目录的 assets/ 目录打包文件。这些文件可以在运行时通过 assets/server 存储挂载点访问。
my-project/
assets/
data.json
templates/
welcome.html
server/
routes/
index.ts
server/routes/index.ts
import { useStorage } from "nitro/storage";
export default defineHandler(async () => {
const serverAssets = useStorage("assets/server");
const keys = await serverAssets.getKeys();
const data = await serverAssets.getItem("data.json");
const template = await serverAssets.getItem("templates/welcome.html");
return { keys, data, template };
});
自定义资源目录
你可以使用 serverAssets 配置选项注册额外的资源目录:
nitro.config.ts
import { defineNitroConfig } from "nitro/config";
export default defineNitroConfig({
serverAssets: [
{
baseName: "templates",
dir: "./templates",
}
]
})
自定义资源目录可通过 assets/<baseName> 访问:
import { useStorage } from "nitro/storage";
const templates = useStorage("assets/templates");
const keys = await templates.getKeys();
const html = await templates.getItem("email.html");
资源元数据
服务器资源包含元数据,例如内容类型、ETag 和修改时间:
import { useStorage } from "nitro/storage";
const serverAssets = useStorage("assets/server");
const meta = await serverAssets.getMeta("image.png");
// { type: "image/png", etag: "\"...\"", mtime: "2024-01-01T00:00:00.000Z" }
// 适用于设置响应头
const raw = await serverAssets.getItemRaw("image.png");
在开发环境中,服务器资源直接从文件系统读取。在生产环境中,它们会被打包并内联到构建输出中。
运行时配置
在挂载点配置直到运行时才知道的场景中,Nitro 可以使用插件在启动期间动态添加挂载点。
plugins/storage.ts
import { useStorage } from "nitro/storage";
import { definePlugin } from "nitro";
import redisDriver from "unstorage/drivers/redis";
export default definePlugin(() => {
const storage = useStorage()
// 从运行时配置或其他来源动态传入凭据
const driver = redisDriver({
base: "redis",
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
/* 其他 redis 连接器选项 */
})
// 挂载驱动
storage.mount("redis", driver)
})
这是一个临时解决方案,更好的解决方案将在未来推出!请持续关注 GitHub 上的此议题。