终于,出现了一个不是怪物的 Bun 面向对象框架
Source: Dev.to
Bun 以惊人的性能数据把门踢开。大家争相测试 Bun.serve(),而第一波框架(Elysia、Hono)则高度聚焦于函数式、极简的 “裸金属” 风格。
它们确实很棒,别误会。但我感觉少了点什么。
来自 .NET、Java,甚至是 Node 中的 NestJS 生态系统时,我们已经习惯了某些模式:依赖注入(DI)、装饰器以及组织成类的控制器。我想要那种稳健的架构,却不想承受一个启动需要 5 秒的框架的重量。我想要 NestJS 的结构,却拥有 Bun 的原始速度。
就在这时,我发现(并开始使用)Carno.js。
什么是 Carno.js?
Carno.js 将自己定义为 “性能优先的框架”,原生运行于 Bun。
它不试图重新发明轮子;它试图 组织 轮子。Carno.js 带来:
- 控制器与装饰器(
@Get、@Post、@Body…),你已经熟悉。 - 依赖注入,原生且轻量。
- 自定义 ORM —— 一个轻量级 ORM,配备 自定义 SQL 构建器(没有 Knex,没有外部查询构建器——只有原始、优化的性能)。
- 真正的模块化 —— 核心体积小。仅在真正需要时安装
@carno.js/orm或@carno.js/queue。
它适用于希望在不牺牲 Bun 原始性能的前提下,构建可扩展、组织良好的 API 的开发者。
安装与要求
-
安装 Bun(v1.0+)。
-
创建文件夹并初始化项目:
mkdir my-carno-project cd my-carno-project bun init -
安装框架核心:
bun add @carno.js/core -
启用装饰器 – Carno 使用经典的装饰器语法,因此请更新
tsconfig.json:{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true // ...other options } }
从零创建项目(逐步指南)
1. 文件夹结构
为了简单起步,保持布局最小化:
src/
├── controllers/
│ └── user.controller.ts
├── services/
│ └── user.service.ts
└── index.ts
2. 创建服务(依赖注入)
Carno 自带内置 DI 容器——无需外部库。
// src/services/user.service.ts
import { Service } from '@carno.js/core';
@Service()
export class UserService {
private users = [
{ id: 1, name: 'Myron' },
{ id: 2, name: 'Bun User' }
];
findAll() {
return this users;
}
create(name: string) {
const newUser = { id: this.users.length + 1, name };
this.users.push(newUser);
return newUser;
}
}
3. 创建控制器
如果你使用过 NestJS 或 Spring,这会很熟悉。注意构造函数中对 UserService 的注入。
// src/controllers/user.controller.ts
import { Controller, Get, Post, Body } from '@carno.js/core';
import { UserService } from '../services/user.service';
@Controller('/users')
export class UserController {
constructor(private userService: UserService) {}
@Get()
getUsers() {
return this.userService.findAll();
}
@Post()
createUser(@Body('name') name: string) {
// Basic validation
if (!name) {
throw new Error('Name is required');
}
return this.userService.create(name);
}
}
4. 入口点
在 index.ts 中将所有内容关联起来。Carno 需要知道你打算使用的控制器和提供者(服务)。
// src/index.ts
import { Carno } from '@carno.js/core';
import { UserController } from './controllers/user.controller';
import { UserService } from './services/user.service';
const app = new Carno({
providers: [
UserService, // Register the service
UserController // Register the controller
]
});
const port = 3000; // Default port 3000 or whatever you pass
app.listen(port);
5. 运行
bun run src/index.ts
完成。没有复杂的构建步骤,也没有慢速的转译。即时运行。
完整示例:模块化
Carno 支持 嵌套路由(子控制器)。当你的 API 规模扩大时,你不需要一个庞大的路由文件。
// Example of a versioned API controller
import { Controller } from '@carno.js/core';
import { UserController } from './controllers/user.controller';
import { ProductController } from './controllers/product.controller';
@Controller({
path: '/api/v1',
children: [UserController, ProductController]
})
export class ApiV1Controller {}
这使得 API 版本管理变得轻而易举。
好处与权衡
✅ 好处
- DX (Developer Experience): 编写类和装饰器对大型团队来说非常易读。
- Performance: 底层使用
Bun.serve——快速。非常快。 - Integrated Ecosystem:
@carno.js/orm和@carno.js/queue遵循相同的模式,因而无需手动拼接不同的库。
⚠️ 权衡
- Maturity: 它比 Express 或 NestJS 更新。你可能会错过在旧项目中依赖的某些冷门插件。
- Bun‑Only: 如果公司政策要求使用 Node.js,Carno 目前(尚)不是选项。
- Community Size: 目前社区规模小于 Hono 或 Elysia,所以你可能需要偶尔阅读源码(说实话,源码相当整洁)。
Practical Performance Tips in Carno
- 使用单例: 默认情况下,服务是单例的。除非绝对必要(例如每个请求的租户数据),否则避免使用
REQUEST范围(ProviderScope.REQUEST),因为实例化类会消耗 CPU。 - JSON 序列化: Carno 会自动序列化对象。控制器中返回普通对象(POJO)而不是带有循环方法的复杂类。
- 缓存: Carno 提供良好的缓存集成。如果某个端点开销大,给它加缓存。
- 关注日志: 在生产环境中使用异步日志记录器(Carno 内部使用
pino;请配置它以避免阻塞主线程)。 - 避免沉重的中间件: Carno 的中间件模型很灵活,但每个中间件都会为请求增加一次“跳转”。保持中间件轻量化。
快速比较
| 框架 | 风格 | 何时使用? |
|---|---|---|
| Carno.js | 面向对象,装饰器,结构化 | 如果你喜欢 NestJS/Java/.NET,但想要 Bun 的速度以及自定义、轻量级的 ORM。 |
| Elysia / Hono | 函数式,极简 | 超轻量微服务、边缘函数,或如果你偏好函数式编程。 |
| NestJS | 面向对象,意见化,大型 | 如果你需要庞大的企业生态系统并在 Node.js 上运行。 |
| Express | 传统 | 旧项目。对于新项目,请避免使用(慢且开发体验过时)。 |
快速常见问题
1. 我可以在 SQL 数据库中使用它吗?
是的!@carno.js/orm 是推荐的方式。它专为此生态系统构建,不带旧查询构建器的负担。
2. 它支持 Validation 吗?
是的,它原生使用 class-validator 和 class-transformer。你可以使用 @IsString() 等装饰器创建 DTO。
3. 它如何与 Testing 配合使用?
Bun 有原生测试运行器(bun test)。由于 Carno 使用依赖注入,在控制器单元测试中“mock”服务非常简单。
4. 它兼容 Node 库吗?
大多数情况下兼容,归功于 Bun 的兼容性。建议使用不依赖晦涩原生 Node API 的库。
5. 我可以在 Serverless 环境中使用它吗?
可以,但 Carno 在容器/长运行进程中更能发挥优势,因为 DI 和结构在此处收益更大。
结论
Carno.js 填补了一个重要空白:结构稳健且不慢。如果你一直在寻找将那个慢速的 Node API 迁移到 Bun 的借口,但又担心失去代码组织结构,不妨试试 Carno。
有用链接
喜欢这个提示吗?你在 Bun 中尝试过任何面向对象的框架吗?在评论中告诉我吧!