Skip to content
我们的赞助商
博客

Elysia 0.4 - 月夜の音楽会 (月夜音乐会)

破碎的玻璃碎片漂浮在深渊中

"The Liar Princess and the Blind Prince" 预告片 的开场音乐命名,「月夜の音楽会」(Moonlit Night Concert) 由 Akiko Shikata 作曲并演唱。

这个版本并没有引入令人兴奋的新功能,而是为更坚实的基础奠定基础,并为 Elysia 的未来进行内部改进。

提前时间编译

默认情况下,Elysia 需要在各种情况下处理条件检查,例如,在执行之前检查路由的生命周期是否存在,或者如果提供了验证模式,则展开它。

这会给 Elysia 和整体带来最小的开销,因为即使路由没有附加生命周期事件,也需要在运行时进行检查。

由于每个函数都在编译时检查,不可能有条件异步,例如,一个简单返回文件的路由应该是同步的,但由于是编译时检查,一些路由可能是异步的,从而使相同的简单路由也成为异步的。

异步函数会为函数引入额外的 tick,使其稍慢一些。但由于 Elysia 是 Web 服务器的基础,我们希望优化每个部分,以确保您不会遇到性能问题。

我们通过引入提前时间编译来修复这个小的开销。

顾名思义,Elysia 不是在运行时检查动态生命周期和验证,而是检查生命周期、验证以及异步函数的可能性,并生成一个紧凑的函数,移除未使用的部分,如未使用的生命周期和验证。

这使得条件异步函数成为可能,因为我们不是使用集中式函数来处理,而是为每个路由特别创建并组合一个新函数。Elysia 然后检查所有生命周期函数和处理程序,看是否有异步,如果没有,则函数将同步以减少额外开销。

TypeBox 0.26

TypeBox 是一个为 Elysia 的验证和类型提供程序提供动力的库,用于创建类型级别的单一事实来源,重导出为 Elysia.t

在本次更新中,我们将 TypeBox 从 0.25.4 更新到 0.26。

这带来了很多改进和新功能,例如 Not 类型和用于 coercion 值的 Convert,我们可能在 Elysia 的下一个版本中支持。

但对 Elysia 的一个好处是,Error.First(),这允许我们获取类型的第一个错误,而不是使用 Iterator,这减少了创建新错误以发送回客户端的开销。

TypeBoxElysia.t 有一些变化,通常不会对您的端产生太大影响,但您可以在 TypeBox 的发布说明中查看新功能。

按状态验证响应

以前,Elysia 的响应使用联合类型验证多个状态响应。

这可能对具有严格状态响应的高度动态应用产生意外结果。 例如,如果您有一个像这样的路由:

ts
app.post('/strict-status', process, {
    schema: {
        response: {
            200: t.String(),
            400: t.Number()
        }
    }
})

预计如果 200 响应不是字符串,则应该抛出验证错误,但实际上不会抛出错误,因为响应验证使用的是联合。这可能会将意外值留给最终用户,并为 Eden Treaty 带来类型错误。

在本版本中,响应按状态而不是联合进行验证,这意味着它将严格基于响应状态进行验证,而不是联合类型。

Elysia Fn 的分离

Elysia Fn 是 Elysia 的一个伟大补充,与 Eden 一起,它打破了客户端和服务器之间的界限,允许您在客户端使用任何服务器端函数,完全类型安全,甚至支持像 Error、Set 和 Map 这样的基本类型。

但由于基本类型支持,Elysia Fn 依赖于 "superjson",它占 Elysia 依赖大小的约 38%。

在本版本中,要使用 Elysia Fn,您需要明确安装 @elysiajs/fn。这种方法类似于安装附加功能,就像 cargo add --feature 一样。

这使不使用 Elysia Fn 的服务器更轻量。遵循我们的理念,确保您拥有实际需要的东西

但是,如果您忘记安装 Elysia Fn 并意外使用它,将会有一个类型警告提醒您在使用前安装 Elysia Fn,以及一个运行时错误告知同样的事情。

对于迁移,除了明确安装 @elysiajs/fn 的破坏性更改之外,没有迁移需求。

条件路由

本版本引入了用于注册条件路由或插件的 .if 方法。

这允许您为特定条件声明性地排除,例如从生产环境中排除 Swagger 文档。

ts
const isProduction = process.env.NODE_ENV === 'production'

const app = new Elysia().if(!isProduction, (app) =>
    app.use(swagger())
)

Eden Treaty 将能够识别路由,就像它是一个普通路由/插件一样。

自定义验证错误

非常感谢 amirrezamahyari 在 #31 中的贡献,这允许 Elysia 访问 TypeBox 的错误属性,以获得更好的程序化错误响应。

ts
new Elysia()
    .onError(({ code, error, set }) => {
        if (code === 'NOT_FOUND') {
            set.status = 404

            return 'Not Found :('
        }

        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 的持续支持~

月夜音乐会,我们的秘密

让我们重新开始,不要放开这只手

月夜音乐会,我们的羁绊

我想告诉你,“你不是骗子”

心中的回忆像不断绽放的花朵

不管你看起来怎样,你都是我的歌姬

今晚陪在我身边

Elysia:人性化框架