Elysia
1,837,294 reqs/sHono
740,451
Measured in requests/second. Result from TechEmpower Benchmark Round 23 (2025-02-24) in JSON serialization
¥From Hono to Elysia
本指南面向 Hono 用户,帮助他们了解 Elysia 与 Hono 之间的差异(包括语法),以及如何通过示例将应用从 Hono 迁移到 Elysia。
¥This guide is for Hono users who want to see a differences from Elysia including syntax, and how to migrate your application from Hono to Elysia by example.
Hono 是基于 Web 标准构建的快速轻量级框架。它与 Deno、Bun、Cloudflare Workers 和 Node.js 等多种运行时广泛兼容。
¥Hono is a fast and lightweight built on Web Standard. It has broad compatibility with multiple runtime like Deno, Bun, Cloudflare Workers, and Node.js.
Elysia 是一个符合人机工程学的 Web 框架。设计符合人机工程学且方便开发者使用,重点关注可靠的类型安全性和性能。
¥Elysia is an ergonomic web framework. Designed to be ergonomic and developer-friendly with a focus on sound type safety and performance.
这两个框架都基于 Web 标准 API 构建,语法略有不同。Hono 提供了与多种运行时的更高兼容性,而 Elysia 则专注于特定的一组运行时。
¥Both frameworks are built on top of Web Standard API, and have slightly different syntax. Hono offers more compatibility with multiple runtimes while Elysia focuses on a specific set of runtimes.
¥Performance
得益于静态代码分析,Elysia 的性能相比 Hono 有显著提升。
¥Elysia has significant performance improvements over Hono thanks to static code analysis.
740,451
Measured in requests/second. Result from TechEmpower Benchmark Round 23 (2025-02-24) in JSON serialization
¥Routing
Hono 和 Elysia 的路由语法相似,使用 app.get()
和 app.post()
方法来定义路由,路径参数语法也相似。
¥Hono and Elysia has similar routing syntax, using app.get()
and app.post()
methods to define routes and similar path parameters syntax.
两者都使用单个 Context
参数来处理请求和响应,并直接返回响应。
¥Both use a single Context
parameters to handle request and response, and return a response directly.
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => {
return c.text('Hello World')
})
app.post('/id/:id', (c) => {
c.status(201)
return c.text(req.params.id)
})
export default app
Hono 使用辅助函数
c.text
和c.json
返回响应
import { Elysia } from 'elysia'
const app = new Elysia()
.get('/', 'Hello World')
.post(
'/id/:id',
({ status, params: { id } }) => {
return status(201, id)
}
)
.listen(3000)
Elysia 使用单个
context
并直接返回响应
Hono 使用 c.text
和 c.json
来扭曲响应,而 Elysia 会自动将值映射到响应。
¥While Hono use a c.text
, and c.json
to warp a response, Elysia map a value to a response automatically.
样式指南略有不同,Elysia 建议使用方法链和对象解构。
¥There is a slight different in style guide, Elysia recommends usage of method chaining and object destructuring.
Hono 的端口分配取决于运行时和适配器,而 Elysia 使用单一的 listen
方法启动服务器。
¥Hono port allocation is depends on runtime, and adapter while Elysia use a single listen
method to start the server.
¥Handler
Hono 使用函数手动解析查询、标头和正文,而 Elysia 自动解析属性。
¥Hono use a function to parse query, header, and body manually while Elysia automatically parse properties.
import { Hono } from 'hono'
const app = new Hono()
app.post('/user', async (c) => {
const limit = c.req.query('limit')
const { name } = await c.body()
const auth = c.req.header('authorization')
return c.json({ limit, name, auth })
})
Hono 会自动解析请求体,但不适用于查询和请求头。
import { Elysia } from 'elysia'
const app = new Elysia()
.post('/user', (ctx) => {
const limit = ctx.query.limit
const name = ctx.body.name
const auth = ctx.headers.authorization
return { limit, name, auth }
})
Elysia 使用静态代码分析来分析要解析的内容
Elysia 使用静态代码分析来确定要解析的内容,并且只解析所需的属性。
¥Elysia use static code analysis to determine what to parse, and only parse the required properties.
这对于性能和类型安全非常有用。
¥This is useful for performance and type safety.
¥Subrouter
两者都可以继承另一个实例作为路由,但 Elysia 将每个实例都视为可用作子路由的组件。
¥Both can inherits another instance as a router, but Elysia treat every instances as a component which can be used as a subrouter.
import { Hono } from 'hono'
const subRouter = new Hono()
subRouter.get('/user', (c) => {
return c.text('Hello User')
})
const app = new Hono()
app.route('/api', subRouter)
Hono require 用于分隔子路由的前缀
¥a prefix to separate the subrouter
import { Elysia } from 'elysia'
const subRouter = new Elysia({ prefix: '/api' })
.get('/user', 'Hello User')
const app = new Elysia()
.use(subRouter)
Elysia 使用可选的前缀构造函数来定义一个
Hono 需要前缀来分隔子路由,而 Elysia 无需前缀。
¥While Hono requires a prefix to separate the subrouter, Elysia doesn't require a prefix to separate the subrouter.
¥Validation
Hono 通过外部包支持各种验证器,而 Elysia 内置了使用 TypeBox 的验证功能,并支持开箱即用的标准 Schema,让你无需额外依赖库即可使用你常用的库,例如 Zod、Valibot、ArkType、Effect Schema 等。Elysia 还提供与 OpenAPI 的无缝集成,并在后台进行类型推断。
¥While Hono supports for various validator via external package, Elysia has a built-in validation using TypeBox, and support for Standard Schema out of the box allowing you to use your favorite library like Zod, Valibot, ArkType, Effect Schema and so on without additional library. Elysia also offers seamless integration with OpenAPI, and type inference behind the scene.
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
const app = new Hono()
app.patch(
'/user/:id',
zValidator(
'param',
z.object({
id: z.coerce.number()
})
),
zValidator(
'json',
z.object({
name: z.string()
})
),
(c) => {
return c.json({
params: c.req.param(),
body: c.req.json()
})
}
)
崩坏 3 使用基于管道
import { Elysia, t } from 'elysia'
const app = new Elysia()
.patch('/user/:id', ({ params, body }) => ({
params,
body
}),
{
params: t.Object({
id: t.Number()
}),
body: t.Object({
name: t.String()
})
})
import { Elysia } from 'elysia'
import { z } from 'zod'
const app = new Elysia()
.patch('/user/:id', ({ params, body }) => ({
params,
body
}),
{
params: z.object({
id: z.number()
}),
body: z.object({
name: z.string()
})
})
import { Elysia } from 'elysia'
import * as v from 'zod'
const app = new Elysia()
.patch('/user/:id', ({ params, body }) => ({
params,
body
}),
{
params: v.object({
id: v.number()
}),
body: v.object({
name: v.string()
})
})
Elysia 使用 TypeBox 进行验证,并自动强制类型转换。同时支持使用相同语法的各种验证库,例如 Zod、Valibot。
两者都自动提供从模式到上下文的类型推断。
¥Both offers type inference from schema to context automatically.
¥File upload
Hono 和 Elysia 都使用 Web 标准 API 来处理文件上传,但 Elysia 内置了声明式文件验证功能,使用 file-type 来验证 mimetype。
¥Both Hono, and Elysia use Web Standard API to handle file upload, but Elysia has a built-in declarative support for file validation using file-type to validate mimetype.
import { Hono } from 'hono'
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'
import { fileTypeFromBlob } from 'file-type'
const app = new Hono()
app.post(
'/upload',
zValidator(
'form',
z.object({
file: z.instanceof(File)
})
),
async (c) => {
const body = await c.req.parseBody()
const type = await fileTypeFromBlob(body.image as File)
if (!type || !type.mime.startsWith('image/')) {
c.status(422)
return c.text('File is not a valid image')
}
return new Response(body.image)
}
)
Hono 需要一个单独的
file-type
库来验证 mimetype
import { Elysia, t } from 'elysia'
const app = new Elysia()
.post('/upload', ({ body }) => body.file, {
body: t.Object({
file: t.File({
type: 'image'
})
})
})
Elysia 处理文件,并以声明方式进行 mimetype 验证
由于 Web 标准 API 不验证 mimetype,信任客户端提供的 content-type
存在安全风险,因此 Hono 需要外部库,而 Elysia 使用 file-type
自动验证 mimetype。
¥As Web Standard API doesn't validate mimetype, it is a security risk to trust content-type
provided by the client so external library is required for Hono, while Elysia use file-type
to validate mimetype automatically.
¥Middleware
Hono 中间件使用类似于 Express 的基于队列的单线程,而 Elysia 使用基于事件的生命周期提供更精细的控制。
¥Hono middleware use a single queue-based order similar to Express while Elysia give you a more granular control using an event-based lifecycle.
Elysia 的生命周期事件如下图所示。
¥Elysia's Life Cycle event can be illustrated as the following.
点击图片放大
虽然 Hono 按顺序具有单个请求管道流,但 Elysia 可以拦截请求管道中的每个事件。
¥While Hono has a single flow for request pipeline in order, Elysia can intercept each event in a request pipeline.
import { Hono } from 'hono'
const app = new Hono()
// Global middleware
app.use(async (c, next) => {
console.log(`${c.method} ${c.url}`)
await next()
})
app.get(
'/protected',
// Route-specific middleware
async (c, next) => {
const token = c.headers.authorization
if (!token) {
c.status(401)
return c.text('Unauthorized')
}
await next()
},
(req, res) => {
res.send('Protected route')
}
)
Hono 使用基于队列的单向执行中间件
import { Elysia } from 'elysia'
const app = new Elysia()
// Global middleware
.onRequest(({ method, path }) => {
console.log(`${method} ${path}`)
})
// Route-specific middleware
.get('/protected', () => 'protected', {
beforeHandle({ status, headers }) {
if (!headers.authorizaton)
return status(401)
}
})
Elysia 在请求管道中的每个点使用特定的事件拦截器
虽然 Hono 有一个 next
函数来调用下一个中间件,但 Elysia 没有。
¥While Hono has a next
function to call the next middleware, Elysia does not has one.
¥Sounds type safety
Elysia 的设计注重类型安全。
¥Elysia is designed to be sounds type safety.
例如,你可以使用 derive 和 resolve 以类型安全的方式自定义上下文,而 Hono 则不行。
¥For example, you can customize context in a type safe manner using derive and resolve while Hono doesn't.
import { Hono } from 'hono'
import { createMiddleware } from 'hono/factory'
const app = new Hono()
const getVersion = createMiddleware(async (c, next) => {
c.set('version', 2)
await next()
})
app.use(getVersion)
app.get('/version', getVersion, (c) => {
return c.text(c.get('version') + '')No overload matches this call.
Overload 1 of 2, '(key: never): unknown', gave the following error.
Argument of type '"version"' is not assignable to parameter of type 'never'.
Overload 2 of 2, '(key: never): never', gave the following error.
Argument of type '"version"' is not assignable to parameter of type 'never'.})
const authenticate = createMiddleware(async (c, next) => {
const token = c.req.header('authorization')
if (!token) {
c.status(401)
return c.text('Unauthorized')
}
c.set('token', token.split(' ')[1])
await next()
})
app.post('/user', authenticate, async (c) => {
c.get('version')No overload matches this call.
Overload 1 of 2, '(key: never): unknown', gave the following error.
Argument of type '"version"' is not assignable to parameter of type 'never'.
Overload 2 of 2, '(key: never): never', gave the following error.
Argument of type '"version"' is not assignable to parameter of type 'never'.
return c.text(c.get('token'))No overload matches this call.
Overload 1 of 2, '(key: never): unknown', gave the following error.
Argument of type '"token"' is not assignable to parameter of type 'never'.
Overload 2 of 2, '(key: never): never', gave the following error.
Argument of type '"token"' is not assignable to parameter of type 'never'.No overload matches this call.
Overload 1 of 2, '(text: string, status?: ContentfulStatusCode | undefined, headers?: HeaderRecord | undefined): Response & TypedResponse<string, ContentfulStatusCode, "text">', gave the following error.
Argument of type 'unknown' is not assignable to parameter of type 'string'.
Overload 2 of 2, '(text: string, init?: ResponseOrInit<ContentfulStatusCode> | undefined): Response & TypedResponse<string, ContentfulStatusCode, "text">', gave the following error.
Argument of type 'unknown' is not assignable to parameter of type 'string'.})
Hono 使用中间件来扩展上下文,但类型不安全
import { Elysia } from 'elysia'
const app = new Elysia()
.decorate('version', 2)
.get('/version', ({ version }) => version)
.resolve(({ status, headers: { authorization } }) => {
if(!authorization?.startsWith('Bearer '))
return status(401)
return {
token: authorization.split(' ')[1]
}
})
.get('/token', ({ token, version }) => {
version
return token
})
Elysia 在请求管道中的每个点使用特定的事件拦截器
虽然 Hono 可以使用 declare module
扩展 ContextVariableMap
接口,但它是全局可用的,并且不具备良好的类型安全性,并且不能保证该属性在所有请求处理程序中都可用。
¥While Hono can, use declare module
to extend the ContextVariableMap
interface, it is globally available and doesn't have sounds type safety, and doesn't garantee that the property is available in all request handlers.
declare module 'hono' {
interface ContextVariableMap {
version: number
token: string
}
}
这是上述 Hono 示例运行所必需的,它不提供声音类型安全。
¥Middleware parameter
Hono 使用回调函数定义可复用的特定路由中间件,而 Elysia 使用 macro 函数定义自定义钩子。
¥Hono use a callback function to define a reusable route-specific middleware, while Elysia use macro to define a custom hook.
import { Hono } from 'hono'
import { createMiddleware } from 'hono/factory'
const app = new Hono()
const role = (role: 'user' | 'admin') => createMiddleware(async (c, next) => {
const user = findUser(c.req.header('Authorization'))
if(user.role !== role) {
c.status(401)
return c.text('Unauthorized')
}
c.set('user', user)
await next()
})
app.get('/user/:id', role('admin'), (c) => {
return c.json(c.get('user'))No overload matches this call.
Overload 1 of 2, '(key: never): unknown', gave the following error.
Argument of type '"user"' is not assignable to parameter of type 'never'.
Overload 2 of 2, '(key: never): never', gave the following error.
Argument of type '"user"' is not assignable to parameter of type 'never'.})
Hono 使用回调返回
createMiddleware
来创建可重用的中间件,但类型不安全
import { Elysia } from 'elysia'
const app = new Elysia()
.macro({
role: (role: 'user' | 'admin') => ({
resolve({ status, headers: { authorization } }) {
const user = findUser(authorization)
if(user.role !== role)
return status(401)
return {
user
}
}
})
})
.get('/token', ({ user }) => user, {
role: 'admin'
})
Elysia 使用宏将自定义参数传递给自定义中间件
¥Error handling
Hono 提供了一个适用于所有路由的 onError
函数,而 Elysia 则提供了更精细的错误处理控制。
¥Hono provide a onError
function which apply to all routes while Elysia provides a more granular control over error handling.
import { Hono } from 'hono'
const app = new Hono()
class CustomError extends Error {
constructor(message: string) {
super(message)
this.name = 'CustomError'
}
}
// global error handler
app.onError((error, c) => {
if(error instanceof CustomError) {
c.status(500)
return c.json({
message: 'Something went wrong!',
error
})
}
})
// route-specific error handler
app.get('/error', (req, res) => {
throw new CustomError('oh uh')
})
Hono 使用
onError
函数处理错误,所有路由使用同一个错误处理程序
import { Elysia } from 'elysia'
class CustomError extends Error {
// Optional: custom HTTP status code
status = 500
constructor(message: string) {
super(message)
this.name = 'CustomError'
}
// Optional: what should be sent to the client
toResponse() {
return {
message: "If you're seeing this, our dev forgot to handle this error",
error: this
}
}
}
const app = new Elysia()
// Optional: register custom error class
.error({
CUSTOM: CustomError,
})
// Global error handler
.onError(({ error, code }) => {
if(code === 'CUSTOM')
return {
message: 'Something went wrong!',
error
}
})
.get('/error', () => {
throw new CustomError('oh uh')
}, {
// Optional: route specific error handler
error({ error }) {
return {
message: 'Only for this route!',
error
}
}
})
Elysia 提供更精细的错误处理控制和作用域机制
Hono 提供类似中间件的错误处理,而 Elysia 提供:
¥While Hono offers error handling using middleware-like, Elysia provide:
toResponse
错误代码对于日志记录和调试非常有用,并且在区分扩展同一类的不同错误类型时非常重要。
¥The error code is useful for logging and debugging, and is important when differentiating between different error types extending the same class.
¥Encapsulation
Hono 封装了插件的副作用,而 Elysia 通过显式的作用域机制和代码顺序让你可以控制插件的副作用。
¥Hono encapsulate plugin side-effect, while Elysia give you a control over side-effect of a plugin via explicit scoping mechanism, and order-of-code.
import { Hono } from 'hono'
const subRouter = new Hono()
subRouter.get('/user', (c) => {
return c.text('Hello User')
})
const app = new Hono()
app.route('/api', subRouter)
Hono 封装了插件的副作用
import { Elysia } from 'elysia'
const subRouter = new Elysia()
.onBeforeHandle(({ status, headers: { authorization } }) => {
if(!authorization?.startsWith('Bearer '))
return status(401)
})
const app = new Elysia()
.get('/', 'Hello World')
.use(subRouter)
// doesn't have side-effect from subRouter
.get('/side-effect', () => 'hi')
除非明确说明,否则 Elysia 会封装插件的副作用。
两者都具有插件的封装机制,以防止副作用。
¥Both has a encapsulate mechanism of a plugin to prevent side-effect.
然而,Elysia 可以通过声明作用域来明确指定哪个插件应该具有副作用,而 Fastify 始终会对其进行封装。
¥However, Elysia can explicitly stated which plugin should have side-effect by declaring a scoped while Fastify always encapsulate it.
import { Elysia } from 'elysia'
const subRouter = new Elysia()
.onBeforeHandle(({ status, headers: { authorization } }) => {
if(!authorization?.startsWith('Bearer '))
return status(401)
})
// Scoped to parent instance but not beyond
.as('scoped')
const app = new Elysia()
.get('/', 'Hello World')
.use(subRouter)
// now have side-effect from subRouter
.get('/side-effect', () => 'hi')
Elysia 提供三种作用域机制:
¥Elysia offers 3 type of scoping mechanism:
由于 Hono 不提供作用域机制,我们需要:
¥As Hono doesn't offers a scoping mechanism, we need to either:
然而,如果处理不当,这可能会导致重复的副作用。
¥However, this can caused a duplicated side-effect if not handled carefully.
import { Hono } from 'hono'
import { createMiddleware } from 'hono/factory'
const middleware = createMiddleware(async (c, next) => {
console.log('called')
await next()
})
const app = new Hono()
const subRouter = new Hono()
app.use(middleware)
app.get('/main', (c) => c.text('Hello from main!'))
subRouter.use(middleware)
// This would log twice
subRouter.get('/sub', (c) => c.text('Hello from sub router!'))
app.route('/sub', subRouter)
export default app
在这种情况下,Elysia 提供了插件去重机制,以防止重复的副作用。
¥In this scenario, Elysia offers a plugin deduplication mechanism to prevent duplicated side-effect.
import { Elysia } from 'elysia'
const subRouter = new Elysia({ name: 'subRouter' })
.onBeforeHandle(({ status, headers: { authorization } }) => {
if(!authorization?.startsWith('Bearer '))
return status(401)
})
.as('scoped')
const app = new Elysia()
.get('/', 'Hello World')
.use(subRouter)
.use(subRouter)
.use(subRouter)
.use(subRouter)
// side-effect only called once
.get('/side-effect', () => 'hi')
通过使用唯一的 name
,Elysia 只需应用一次插件,不会造成重复的副作用。
¥By using a unique name
, Elysia will apply the plugin only once, and will not cause duplicated side-effect.
Hono 在 hono/cookie
下内置了 cookie 实用函数,而 Elysia 使用基于信号的方法来处理 cookie。
¥Hono has a built-in cookie utility functions under hono/cookie
, while Elysia use a signal-based approach to handle cookies.
import { Hono } from 'hono'
import { getSignedCookie, setSignedCookie } from 'hono/cookie'
const app = new Hono()
app.get('/', async (c) => {
const name = await getSignedCookie(c, 'secret', 'name')
await setSignedCookie(
c,
'name',
'value',
'secret',
{
maxAge: 1000,
}
)
})
Hono 使用实用函数来处理 Cookie
import { Elysia } from 'elysia'
const app = new Elysia({
cookie: {
secret: 'secret'
}
})
.get('/', ({ cookie: { name } }) => {
// signature verification is handle automatically
name.value
// cookie signature is signed automatically
name.value = 'value'
name.maxAge = 1000 * 60 * 60 * 24
})
Elysia 使用基于信号的方法来处理 Cookie
Hono 需要额外的精力来描述规范,而 Elysia 可以将规范无缝集成到架构中。
¥Hono require additional effort to describe the specification, while Elysia seamless integrate the specification into the schema.
import { Hono } from 'hono'
import { describeRoute, openAPISpecs } from 'hono-openapi'
import { resolver, validator as zodValidator } from 'hono-openapi/zod'
import { swaggerUI } from '@hono/swagger-ui'
import { z } from '@hono/zod-openapi'
const app = new Hono()
const model = z.array(
z.object({
name: z.string().openapi({
description: 'first name only'
}),
age: z.number()
})
)
const detail = await resolver(model).builder()
console.log(detail)
app.post(
'/',
zodValidator('json', model),
describeRoute({
validateResponse: true,
summary: 'Create user',
requestBody: {
content: {
'application/json': { schema: detail.schema }
}
},
responses: {
201: {
description: 'User created',
content: {
'application/json': { schema: resolver(model) }
}
}
}
}),
(c) => {
c.status(201)
return c.json(c.req.valid('json'))
}
)
app.get('/ui', swaggerUI({ url: '/doc' }))
app.get(
'/doc',
openAPISpecs(app, {
documentation: {
info: {
title: 'Hono API',
version: '1.0.0',
description: 'Greeting API'
},
components: {
...detail.components
}
}
})
)
export default app
Hono 需要额外的精力来描述规范。
import { Elysia, t } from 'elysia'
import { openapi } from '@elysiajs/openapi'
const app = new Elysia()
.use(openapi())
.model({
user: t.Array(
t.Object({
name: t.String(),
age: t.Number()
})
)
})
.post('/users', ({ body }) => body, {
body: 'user',
response: {
201: 'user'
},
detail: {
summary: 'Create user'
}
})
Elysia 将规范无缝集成到模式中
Hono 有单独的函数来描述路由规范和验证,并且需要一些工作才能正确设置。
¥Hono has separate function to describe route specification, validation, and require some effort to setup properly.
Elysia 使用你提供的模式用于生成 OpenAPI 规范,并验证请求/响应,并从单一数据源自动推断类型。
¥Elysia use schema you provide to generate the OpenAPI specification, and validate the request/response, and infer type automatically all from a single source of truth.
Elysia 还将 model
中注册的 Schema 附加到 OpenAPI 规范中,允许你在 Swagger 或 Scalar UI 的专用部分中引用该模型,同时 Hono 会将 Schema 内联到路由中。
¥Elysia also appends the schema registered in model
to the OpenAPI spec, allowing you to reference the model in a dedicated section in Swagger or Scalar UI while Hono inline the schema to the route.
¥Testing
两者都基于 Web 标准 API 构建,因此可以与任何测试库一起使用。
¥Both is built on top of Web Standard API allowing it be used with any testing library.
import { Hono } from 'hono'
import { describe, it, expect } from 'vitest'
const app = new Hono()
.get('/', (c) => c.text('Hello World'))
describe('GET /', () => {
it('should return Hello World', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe('Hello World')
})
})
Hono 内置了
request
方法来执行请求
import { Elysia } from 'elysia'
import { describe, it, expect } from 'vitest'
const app = new Elysia()
.get('/', 'Hello World')
describe('GET /', () => {
it('should return Hello World', async () => {
const res = await app.handle(
new Request('http://localhost')
)
expect(res.status).toBe(200)
expect(await res.text()).toBe('Hello World')
})
})
Elysia 使用 Web 标准 API 处理请求和响应
或者,Elysia 还提供了一个名为 Eden 的辅助库,用于端到端类型安全,允许我们使用自动补全和完全类型安全进行测试。
¥Alternatively, Elysia also offers a helper library called Eden for End-to-end type safety, allowing us to test with auto-completion, and full type safety.
import { Elysia } from 'elysia'
import { treaty } from '@elysiajs/eden'
import { describe, expect, it } from 'bun:test'
const app = new Elysia().get('/hello', 'Hello World')
const api = treaty(app)
describe('GET /', () => {
it('should return Hello World', async () => {
const { data, error, status } = await api.hello.get()
expect(status).toBe(200)
expect(data).toBe('Hello World')
})
})
¥End-to-end type safety
两者都提供端到端的类型安全,但 Hono 似乎不提供基于状态码的类型安全错误处理。
¥Both offers end-to-end type safety, however Hono doesn't seems to offers type-safe error handling based on status code.
import { Hono } from 'hono'
import { hc } from 'hono/client'
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'
const app = new Hono()
.post(
'/mirror',
zValidator(
'json',
z.object({
message: z.string()
})
),
(c) => c.json(c.req.valid('json'))
)
const client = hc<typeof app>('/')
const response = await client.mirror.$post({
json: {
message: 'Hello, world!'
}
})
const data = await response.json()
console.log(data)
Hono 使用
hc
函数执行请求,并提供端到端的类型安全
import { Elysia, t } from 'elysia'
import { treaty } from '@elysiajs/eden'
const app = new Elysia()
.post('/mirror', ({ body }) => body, {
body: t.Object({
message: t.String()
})
})
const api = treaty(app)
const { data, error } = await api.mirror.post({
message: 'Hello World'
})
if(error)
throw error
console.log(data)
Elysia 使用
treaty
运行请求,并提供端到端类型安全
虽然两者都提供端到端的类型安全,但 Elysia 提供了基于状态码的更类型安全的错误处理,而 Hono 则没有。
¥While both offers end-to-end type safety, Elysia offers a more type-safe error handling based on status code while Hono doesn't.
使用每个框架相同用途的代码来测量类型推断速度,Elysia 的类型检查速度比 Hono 快 2.3 倍。
¥Using the same purpose code for each framework to measure type inference speed, Elysia is 2.3x faster than Hono for type checking.
Elysia 需要 536 毫秒来推断 Elysia 和 Eden(点击放大)
Hono 需要 1.27 秒才能推断出 Hono 和 HC 的错误(已中止)(点击放大)
1.27 秒并不反映推断的整个时长,而是从开始到因错误 "类型实例化过深深度甚至可能无限。" 而中止的时长,当模式过大时会发生这种情况。
¥The 1.27 seconds doesn't reflect the entire duration of the inference, but a duration from start to aborted by error "Type instantiation is excessively deep and possibly infinite." which happens when there are too large schema.
Hono HC 显示过深错误
这是由大型模式引起的,Hono 不支持超过 100 条包含复杂主体的路由和响应验证,而 Elysia 没有这个问题。
¥This is caused by the large schema, and Hono doesn't support over a 100 routes with complex body, and response validation while Elysia doesn't have this issue.
Elysia Eden 代码展示了无错误的类型推断
Elysia 具有更快的类型推断性能,并且至少在 2,000 条包含复杂主体和响应验证的路由中没有 "类型实例化过深深度甚至可能无限。"。
¥Elysia has a faster type inference performance, and doesn't have "Type instantiation is excessively deep and possibly infinite." at least up to 2,000 routes with complex body, and response validation.
如果端到端类型安全对你来说很重要,那么 Elysia 是正确的选择。
¥If end-to-end type safety is important for you then Elysia is the right choice.
两者都是基于 Web 标准 API 构建的下一代 Web 框架,但略有不同。
¥Both are the next generation web framework built on top of Web Standard API with slight differences.
Elysia 的设计符合人机工程学且对开发者友好,注重声音类型安全,并且性能优于 Hono。
¥Elysia is designed to be ergonomic and developer-friendly with a focus on sounds type safety, and has beter performance than Hono.
虽然 Hono 与多种运行时(尤其是 Cloudflare Workers)具有广泛的兼容性,并且拥有更大的用户群。
¥While Hono offers a broad compatibility with multiple runtimes, especially with Cloudflare Workers, and a larger user base.
或者,如果你来自其他框架,你可以查看:
¥Alternatively, if you are coming from a different framework, you can check out: