Elysia 0.4 - 月夜的音乐会 (Moonlit Night Concert)
该名称源自于 《骗子公主演唱盲王子》预告片 的开场音乐,由 Akiko Shikata 作曲和演唱的 「月夜的音乐会」(Moonlit Night Concert)。
这个版本没有引入令人兴奋的新功能,而是为 Elysia 的未来打下了更坚实的基础,并进行了内部改进。
提前编译
默认情况下,Elysia 必须处理多种情况下的条件检查,例如,在执行之前检查路由的生命周期是否存在,或在提供的情况下解包验证模式。
这为 Elysia 引入了最小的开销,因为即使路由没有附加生命周期事件,仍需要在运行时进行检查。
由于每个函数都在编译时进行检查,因此不可能有条件的异步,例如,返回文件的简单路由应该是同步的,但由于这是编译时检查,有些路由可能是异步的,从而使相同的简单路由也变成异步的。
异步函数为函数引入额外的周期,导致性能稍慢。但由于 Elysia 是 Web 服务器的基础,我们希望优化每个部分,以确保您不会遇到性能问题。
我们通过引入提前编译来修复这种小开销。
顾名思义,Elysia 会在编译时检查生命周期、验证和异步函数的可能性,并生成一个紧凑的函数,去掉不必要的部分,如未使用的生命周期和验证。
使条件异步函数成为可能,因为我们不再使用一个中央函数来处理,而是为每个路由单独构建一个新函数。然后 Elysia 会检查所有生命周期函数和处理程序,以查看是否存在异步,如果没有,则函数将同步以减少额外开销。
TypeBox 0.26
TypeBox 是一个库,为 Elysia 提供了验证和类型提供者,以创建类型级别的单一真相来源,重新导出为 Elysia.t。
在此更新中,我们将 TypeBox 从 0.25.4 更新到 0.26。
这带来了许多改进和新功能,例如,Not
类型和用于 coercion
值的 Convert
,我们可能会在 Elysia 的下一个版本中支持。
但对 Elysia 的一个好处是,Error.First()
,它允许我们获取第一个类型错误,而不是使用迭代器,这减少了创建新错误以发送回客户端的开销。
对 TypeBox 和 Elysia.t 进行了一些更改,通常不会对您产生太大影响,但您可以在 这里查看 TypeBox 的新功能。
按状态验证响应
之前,Elysia 使用联合类型验证多个状态的响应。
这可能在高度动态的应用程序中产生意想不到的结果,特别是当状态响应严格时。 例如,如果您有一个路由如下:
app.post('/strict-status', process, {
schema: {
response: {
200: t.String(),
400: t.Number()
}
}
})
如果 200 响应不是字符串,那么应该抛出验证错误,但实际上,不会抛出错误,因为响应验证使用的是联合。这可能会导致向最终用户返回意外的值,并对 Eden Treaty 产生类型错误。
此版本将响应按状态验证,而不是使用联合,这意味着它将严格根据响应状态进行验证,而不是联合类型。
分离 Elysia 函数
Elysia 函数是 Elysia 的一个很好的补充,与 Eden 一起,它打破了客户端与服务器之间的界限,使您能够在客户端使用任何服务器端函数,完全类型安全,甚至支持 primitive 类型,如 Error、Set 和 Map。
但是,随着 primitive 类型的支持,Elysia 函数依赖于 "superjson",这大约占 Elysia 的依赖大小的 38%。
在此版本中,使用 Elysia 函数需要您明确安装 @elysiajs/fn
。这种方法类似于安装其他功能,就像 cargo add --feature
一样。
这样,Elysia 对于不使用 Elysia 函数的服务器来说更加轻便,遵循我们的理念,确保您拥有实际需要的功能
然而,如果您忘记安装 Elysia 函数并意外使用了 Elysia 函数,将会出现类型警告,提醒您在使用之前安装 Elysia 函数,并且会有运行时错误提示相同的信息。
在迁移方面,除了需要明确安装 @elysiajs/fn
的重大更改外,没有其他迁移需求。
条件路由
此版本引入了用于注册条件路由或插件的 .if
方法。
这允许您针对特定条件进行声明,例如在生产环境中排除 Swagger 文档。
const isProduction = process.env.NODE_ENV === 'production'
const app = new Elysia().if(!isProduction, (app) =>
app.use(swagger())
)
Eden Treaty 将能够识别该路由,就像它是一个普通路由/插件一样。
自定义验证错误
非常感谢 amirrezamahyari 在 #31 上的贡献,使得 Elysia 能够访问 TypeBox 的错误属性,从而获得更好的程序错误响应。
new Elysia()
.onError(({ code, error, set }) => {
if (code === 'NOT_FOUND') {
set.status = 404
return '未找到 :('
}
if (code === 'VALIDATION') {
set.status = 400
return {
fields: error.all()
}
}
})
.post('/sign-in', () => 'hi', {
schema: {
body: t.Object({
username: t.String(),
password: t.String()
})
}
})
.listen(3000)
现在,您可以为您的 API 创建验证错误,而不仅限于第一个错误。
显著改进:
- 更新 TypeBox 到 0.26.8
- 内联声明响应类型
- 重构某些类型以加快响应速度
- 使用 Typebox
Error().First()
代替迭代 - 添加
innerHandle
用于返回实际响应(进行基准测试)
重大更改:
- 将
.fn
分离到@elysiajs/fn
之后
这个版本可能不是一个具有令人兴奋的新功能的大版本,但它改善了一个坚实的基础,并证明了我对未来 Elysia 计划的概念,使 Elysia 比以前更快、更灵活。
我对未来的展望感到非常兴奋。
感谢您对 Elysia 的持续支持~
月夜的音乐会,我们的秘密
让我们重新开始,不放开这只手
月夜的音乐会,我们的羁绊
我想告诉你,“你不是骗子”
我心中的记忆像一朵不断绽放的花
无论你是什么样子,你是我的歌者
今晚要在我身边