跳转至内容
There is a version suitable for your browser's language settings. Would you like to go to the english language of the site?
主页文档

Milkio 介绍

H1

Milkio 是一个 TypeScript 后端框架,支持 Bun,并且在 Serverless 环境中具备更优秀的性能。

在性能之外,Milkio 还旨在通过优雅的设计、封装复杂概念以及与编辑器的深度集成,最小化开发过程中的挫折和痛苦。在 Milkio 的世界里,我们精心将开发的复杂性藏于幕后。

怎么做到的?

很多时候,只要我们不去考虑一些对我们几乎无关的选项,就会发现,原来生活可以变得这么轻松。

在 Milkio 中,我们将过往开发的复杂性巧妙地包裹了起来。当然,不必担心,这并非意味着,会有一部分传统开发中可以做到的事情,在 Milkio 中会束手无策。在 Milkio 中,我们赋予了你轻易地控制任何细节的能力,以便你可以做到任何你想做到的事情。

忘记复杂的 I/O

在 Milkio 中,没有复杂的控制器和注解,你只需要编写一个简单的方法,并将其放置在 apps 目录中,它就直接可以通过输入和它所在路径相同的 URL 进行调用。你的方法是类型安全的,任何不符合你方法所期望的类型的输入都会被拒绝,符合类型要求但多余的属性都会被剔除。当然,在这背后我们施加了一些“魔法 🪄”,但对你来说,编写 API 就是这么简单。

试试简单地向世界问好…?

/**
* 这是一个向世界问候的API!
* 这些 ~~注释~~ 会被呈现到 **Cookbook** 当中
*/
export const api = defineApi({
meta: {},
async action(params: string) {
return `你好世界! (来自 ${params})`;
},
});

在你的客户端中可以这样调用它,是的,不需要使用什么 Axios 或者 Fetch,你可以轻松构建出一个专属于你的 “Axios”。当你输入路径后,TypeScript 的自动完成功能,就会帮助你补全:

const result = await client.execute("hello-world/say", { params: "🥛 Milkio" });
if (!result.success) return alert(result.message);
console.log(result.data); // 输出: "你好世界! (来自 🥛 Milkio)"

忘记 JavaScript

在 Milkio 中,你只能使用 TypeScript,但这是一件好事!

Milkio 利用 TypeScript 类型来为你的 API 自动实施类型安全,就像前文中所描述的那样。尽管这要求你所有的代码都使用 TypeScript 编写,但这是一笔非常划算的交易。

Milkio 的类型系统经过了大量的设计,可以自动推导你代码中的类型,你可以享受完整的自动完成。同时,得益于 Milkio 在设计时对类型系统的重视,你可以轻易做到从为数据库定义实体,到验证你 API 的参数,编写类型的次数为 0 - 1 次!

端到端的类型安全

每一个 Milkio 工程都自动创建了一个客户端包。在其它的服务器或者客户端中,只要使用这个包,就可以调用你的 API,包含了全部类型和完整的自动完成的“魔法”,像这样:

与 tRPC 等框架不同的是,它是一个独立的、完全属于你的 npm 包,它不强迫你将所有的工程组成一个 monorepo,它也不会泄露你的源代码,它的内部只有你工程的类型。

你可以把它发布到 npm 的公共或私有仓库中,或者直接在另一个工程中在本地安装它。你还可以为它添加生命周期方法,例如在每次发送请求之前自动更新 token 或计算签名,使你的包更加易用。

自由地切换运行时

我们可以自由地切换运行时,这得益于 Milkio 符合 WinterCG 标准。Milkio 的所有的请求与响应都是标准的 Request 和 Response 对象,所有的请求都以符合 WinterCG 标准的 Fetch 发送。没有任何依赖于 Node.js 或者 Bun 的代码。

这意味着除了 Milkio 可以运行在 Node.js 和 Bun 中,还可以运行在 Cloudflare Worker、Vercel Edge Function 等任何地方。

我们有意没有对任何命令进行包装,因此当你阅读 package.json 时,你会发现没有什么 milkio start,而是 bun ./run-serve.ts。当你想使用 Bun 以外的运行时时,只需要替换这些相应的命令就可以了。

并且,我们自己实现了开发时所需要的 Watch、Generate Plugins、Test 等功能,这些功能不依赖于任何运行时,并通过 VS Code 扩展提供。这保证了我们可以轻易地更换运行时,不被任何人所捆绑。

Cookbook

Cookbook 是适用于 Milkio 的文档工具,它可以分析你的代码,并依据注释来为你生成在线文档。其中请求和响应的部分都是自动推断出来的,不需要你编写任何说明。它当前还处于 alpha 阶段,未来,我们还会为 Cookbook 引入更多的功能,来帮助你更愉快地构筑梦想。

Serverless

在 Serverless 时代下,游戏的规则被改变了。

以往,我们的代码运行在单个服务器上,它通常很多的 CPU 核心和很大的内存。而现在,我们的代码往往运行在一个个 Pod 中,它们只拥有一个或更少的 CPU 核心 (是的,有些 Serverless 厂商甚至允许你最少选择 0.05 个) 和很少的内存,但是 Pod 们会随着请求数量增加不断地变多。

以前,创建多个 worker threads 是能充分利用硬件资源的良好手段,框架运行时不会执行具体的代码,而是创建和 CPU 核心数相等的 worker threads 来执行。但是现在,这么做反而是负担,即便只创建一个 worker threads 也对冷启动速度影响很大。

冷启动速度很重要,当一个新的请求到来时,而没有任何一个 Pod 可以复用,Serverless 厂商们就会为你拉起一个新的 Pod。

Milkio 利用生成阶段,提前将你的路由、类型安全代码等生成为静态的代码,这可以加速我们应用的启动速度,就像 AOT 在做的事情。

冷启动速度
- Milkio + Bun (1 APIs)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 2.29ms (1x)
- Milkio + Bun (1024 APIs)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 2.32ms (1.01x)
- NestJS + Bun (1 APIs)
███████████████░░░░░░░░░░░░░░░░░░░░░░░░░ 268.53ms (117.26x)
- NestJS + Bun (1024 APIs)
████████████████████████████████████████ 713.13ms (311.41x)
Use Macbook Pro 2023

同时,每个 API 都是懒惰加载的,在实际情况下,通常只有一些 API 是热门的,而更多 API 的则是冷门的。而 Pod 的生命周期一般很短,如果我们像以往那样,在启动时就将所有的 API 加载在内存中,除了会导致很长的启动时间之外,还会导致许多内存被浪费。Milkio 只会在 API 被真正调用时才加载它。

内存使用 (首次调用API在启动后)
- Milkio + Bun (1 APIs)
███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 6.02 MB (1x)
- Milkio + Bun (1024 APIs)
████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 6.39 MB (1.06x)
- NestJS + Bun (1 APIs)
██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 18.04 MB (3.00x)
- NestJS + Bun (1024 APIs)
████████████████████████████████████████ 72.11 MB (11.97x)
Use Macbook Pro 2023

前置知识

Milkio 是一个在设计上尽可能地追求简单易懂的框架,但是仍然需要你了解 TypeScript 的基础语法(变量、函数、条件语句、循环、闭包函数、模块)和类型系统(包括基础类型、联合类型、泛型)。如果你还没有全部熟悉这些知识点,就先去学习一下吧!在哔哩哔哩上,有大量优秀且免费的视频课程。

有想问的吗?

欢迎加入我的 QQ 频道!我和其他正在使用 Milkio 的用户,都很愿意为你解答~