Nitro 从基础到实践
一、Nitro 是什么
Nitro 是一个跨运行时,轻量级,高性能的服务端引擎。可以简单理解成:服务端开发框架 + 运行时适配 + 构建工具 。
服务端运行时
- 物理机部署:Node.js,deno等等
- edge 平台:Cloudflare Workers,Vercel Edge Functions,Netlify Edge Handlers等等
- Serverless平台:AWS Lambda,Azure Functions,Google Cloud Functions等等
服务端引擎
在于它把服务端开发、构建和部署适配整合成了一套统一开发模型。
二、为什么会有 Nitro
传统的服务端开发方式,通常默认目标环境就是一个Node.js 进程。但在现代工程里,服务端场景已经变得复杂很多:
- 有些服务部署在 Node.js 服务器上
- 有些接口部署在 Serverless 平台上
- 有些逻辑希望跑在边缘节点上
- 同一个项目可能同时面对多种部署目标
这会带来几个问题:
- 代码容易和某个具体平台强绑定
- 迁移平台时改造成本高
- 服务端逻辑、构建过程、部署适配经常是割裂的
Nitro 解决的核心问题不是“多一个服务端开发框架”,而是:如何让一套服务端代码尽可能以统一方式开发,并运行在不同平台上。
三、Nitro 的核心设计思想
1. 统一请求处理模型
Nitro 会屏蔽底层平台差异,对外提供统一的服务端处理方式。开发者不需要围绕每个平台的原生请求对象分别写一套逻辑,而是尽量用一致的接口处理请求、响应、参数、状态码和头信息。
这意味着业务代码更关注“处理什么”,而不是“当前平台怎么处理”。
2. 服务端目录组织方式(约定大于配置
Nitro 很适合通过目录和文件来组织服务端入口,例如 API 路由、服务端中间件、工具模块、公共逻辑等。这样的组织方式对前端工程师尤其友好,因为结构清晰、约定明确、上手快。
nitro
├── .gitignore
├── .nitro/
├── nitro.config.ts
├── node_modules/
├── package.json
├── README.md
├── tsconfig.json
└── server/
├── api/
├── plugins/
├── routes/
│ └── index.ts
└── utils/
3. 构建优先,而不是只看运行时
传统服务端框架更强调运行期行为,Nitro 则把“构建产物”也视为一等公民。服务端代码并不是简单地原样部署,而是经过打包、裁剪、适配后输出成符合目标平台要求的产物。
这也是 Nitro 能支持多种部署目标的重要原因。
4. 平台适配优先
Nitro 的一个核心工程目标是把平台差异尽量收敛到框架内部,而不是扩散到业务代码层。也就是说,开发者应该主要围绕统一接口写代码,而不是在业务中到处判断当前运行在 Node、Serverless 还是 Edge。
四、Nitro 能做什么
从项目实践看,Nitro 适合承担这些职责:
- 提供 API 服务
- 作为 BFF 层聚合多个后端接口
- 做请求转发、代理和协议适配
- 做鉴权、参数校验、缓存
- 处理边缘节点逻辑
- 作为前端项目旁边的轻量服务层
- 为静态内容补充动态服务能力
它特别适合“轻服务层”和“中间层”场景。
比如一个典型的 BFF 场景里,浏览器并不直接请求多个下游服务,而是先请求 Nitro 服务,由 Nitro 完成:
- 用户身份校验
- 聚合多个接口
- 统一错误处理
- 缓存数据
- 返回前端真正需要的数据结构
五、Nitro 和传统后端框架的区别
如果拿 Nitro 和 Express、Koa、Fastify 这类框架做对比,可以抓住一个核心点:
传统框架更偏向 Node.js 的运行时开发,Nitro 更偏向跨运行环境的统一开发与构建。
简单理解:
- Express/Koa 重点是如何在 Node 里组织中间件和处理请求
- Fastify 重点是高性能、插件体系和 Node 服务治理
- Nitro 重点是统一开发模型、构建产物和多平台部署适配
如果你的场景是:
- 只跑单一 Node 服务
- 业务复杂度高
- 强依赖特定 Node 能力
那传统框架通常更直接。
如果你的场景是:
- 需要轻量服务层
- 需要多平台部署
- 希望统一开发体验
那 Nitro 的价值会更明显。
六、Nitro 的核心特性
1. 路由能力
Nitro 支持将服务端路由按文件和目录组织。这样做的好处是:
- 路由定义直观
- 代码结构天然分层
- 更容易按业务模块拆分
2. 中间件能力
Nitro 可以在请求进入业务处理前插入通用逻辑,例如:
- 记录请求日志
- 做统一鉴权
- 注入上下文信息
- 处理跨域
- 拦截非法请求
3. 运行时工具能力
Nitro 不只是把请求分发到处理函数,它还会围绕请求处理提供一系列运行时工具,例如:
- 获取请求参数
- 读取请求头
- 设置响应状态码
- 返回 JSON 数据
- 处理错误响应
4. 缓存
Nitro 提供了一个构建在存储层之上的缓存系统。缓存接口请求数据。
// 请求结果缓存一个小时
export default defineCachedEventHandler(event => {}, { maxAge: 60 * 60 });
5. KV存储
Nitro 还提供了一个抽象的存储接口,开发者可以通过它来读写文件、对象存储等。这对于一些需要处理文件上传、生成静态资源、或者在服务端维护一些持久化数据的场景非常有用。
// Default storage is in memory
await useStorage().setItem("test:foo", { hello: "world" });
await useStorage().getItem("test:foo");
// You can also specify the base in useStorage(base)
await useStorage("test").setItem("foo", { hello: "world" });
驱动配置:
export default defineNitroConfig({
storage: {
redis: {
driver: "redis"
/* redis connector options */
},
db: {
driver: "fs",
base: "./data/db"
}
}
});
6. 数据库
Nitro 提供了内置的轻量级 SQL 数据库层。开发者可以在上面构建自己的数据库访问逻辑。这种设计既保持了灵活性,又能满足大多数项目对数据库访问的需求。
- 内置 SQLite 驱动
- 也支持自定义数据库驱动
- 支持集成Orm框架
- 多环境配置数据库链接
代码分割
Nitro 支持把服务端代码分割成多个模块,按需加载。这对于大型项目来说非常重要,因为它可以:
- 减少初始加载时间
- 优化内存使用
- 提高运行效率
6. 构建与部署适配能力
Nitro 的强项之一,是把服务端代码输出成适合不同平台的产物。这个能力对工程落地非常关键,因为它意味着:
- 本地开发不必强绑定最终部署平台
- 迁移部署目标时成本更低
- 同一套服务端逻辑能适配更多基础设施方案
支持的部署平台
- edge workers: Nitro 为部署到 Edge Workers 提供开箱即用的支持。
- runtimes: Nitro 可以构建适用于各种运行时环境的产物,包括 Node.js、deno等。
- providers: Nitro 支持多种云服务提供商,方便在不同基础设施上部署。
- 自定义平台: Nitro 还允许开发者通过自定义适配器来支持其他平台,提供了极大的灵活性。
八、Nitro 适合什么项目
1. BFF 项目
Nitro 非常适合的场景。BFF 的核心诉求通常不是复杂领域建模,而是:
- 接口聚合
- 参数整理
- 权限控制
- 统一返回结构
- 降低前端复杂度
2. 轻量 API 服务
如果项目需要的是一层轻量接口服务,而不是一个重型后端单体项目,Nitro 会是比较合适的选择。特别是那种:
- 业务逻辑不算特别重
- 强调快速开发
- 强调部署灵活性
- 需要适配多种运行平台
3. 边缘服务
如果项目希望把部分逻辑放到离用户更近的位置执行,比如:
- 重定向
- 鉴权逻辑
- 请求拦截
- 缓存命中
4. 前端主导的全栈项目
当团队主要由前端工程师驱动,而又需要一定服务端能力时,Nitro 的学习成本和组织方式通常更友好。因为它强调的是统一约定、目录化组织和现代工程化体验,而不是传统后端体系里大量概念。