Node.js 框架综述 2024 — Elysia / Hono / Nest / Encore — 你应该选择哪一个?

2025-05-24

Node.js 框架综述 2024 — Elysia / Hono / Nest / Encore — 你应该选择哪一个?

Node.js Web 框架——我们从哪里开始呢?市面上有这么多选择,为你的项目选择合适的框架可能会让人不知所措。

在这篇文章中,我将带您了解Node.js 生态系统中最热门的框架,并分析每个框架的优势、劣势和最佳用例。

无论您追求的是速度、可扩展性还是简单性,我们都希望能够涵盖所有内容 - 因此到最后,您将确切地知道哪个框架适合您。

我们将要研究的框架是:NestElysiaEncore.tsHono

视频版本:

开始了!

功能概述

按照从最轻量级到功能最丰富的等级,我会将框架定位如下:

功能概述

这并不意味着轻量级不好,只是取决于你的项目需求。Hono 的轻量级特性实际上是的卖点之一,不到 14KB 的大小非常适合部署到 Cloudflare Workers。

另一方面,Encore.ts具有许多内置功能,例如开箱即用的自动跟踪和本地基础设施。

让我们看一下每个框架,我们将从 Encore.ts 开始

安可

这是一个 开源 框架,旨在简化使用 TypeScript 构建健壮且类型安全的后端的过程。该框架内置了大量工具,可让您的开发体验更加流畅,性能也更加出色。在本次比较的所有框架中,它的速度最快

Encore内置了请求验证功能。您在常规 TypeScript 中定义的请求和响应类型可用于在编译和运行时验证请求。与其他框架不同,Encore 的实际验证是在 Rust 中完成的,而不是在 JavaScript 中。这使得验证速度非常快,稍后会详细介绍。

import {api, Header, Query} from "encore.dev/api";

enum EnumType {
  FOO = "foo",
  BAR = "bar",
}

// Encore.ts automatically validates the request schema 
// and returns and error if the request does not match.
interface RequestSchema {
  foo: Header<"x-foo">;
  name?: Query<string>;

  someKey?: string;
  someOtherKey?: number;
  requiredKey: number[];
  nullableKey?: number | null;
  multipleTypesKey?: boolean | number;
  enumKey?: EnumType;
}

// Validate a request
export const schema = api(
  {expose: true, method: "POST", path: "/validate"},
  (data: RequestSchema): { message: string } => {
    console.log(data);
    return {message: "Validation succeeded"};
  },
);

Enter fullscreen mode Exit fullscreen mode

Encore 让创建和调用服务变得简单。从代码角度来看,服务就像代码库中的另一个文件夹。调用服务中的端点就像调用常规函数一样。但更酷的是,这些函数调用在底层会转换为实际的 HTTP 调用。部署时,您甚至可以选择将服务部署到单独的实例,例如 Kubernetes 集群,同时仍将所有服务代码保留在同一个代码库中。

导入服务并像常规函数一样调用其 API 端点

import { api } from "encore.dev/api";
import { hello } from "~encore/clients"; // import 'hello' service

export const myOtherAPI = api({}, async (): Promise<void> => {
  // all the ping endpoint using a function call
  const resp = await hello.ping({ name: "World" });
  console.log(resp.message); // "Hello World!"
});
Enter fullscreen mode Exit fullscreen mode

使用 Encore.ts,您可以将基础架构作为类型安全的对象集成到应用程序代码中。创建数据库或发布/订阅主题只需几行应用程序代码。Encore.ts 会将您的应用程序构建为 Docker 镜像,您只需在部署时提供运行时配置即可。

用一行代码创建 PostgreSQL 数据库

import { SQLDatabase } from "encore.dev/storage/sqldb";

const db = new SQLDatabase("userdb", {migrations: "./migrations"});
// ... use db.query to query the database.
Enter fullscreen mode Exit fullscreen mode

创建 Pub/Sub 主题和订阅

import { Topic } from "encore.dev/pubsub";

export interface User { /* fields ... */ }

const signups = new Topic<User>("signup", {
  deliveryGuarantee: "at-least-once",
});

await signups.publish({ ... });
Enter fullscreen mode Exit fullscreen mode

Encore 还内置了开发仪表盘。启动 Encore 应用后,开发仪表盘会在localhost:9400端口上显示。您可以从这里调用您的端点,有点像 Postman。每次调用应用程序都会生成跟踪记录,您可以检查这些跟踪记录以查看 API 请求、数据库调用和 Pub/Sub 消息。本地开发仪表盘还包含自动生成的 API 文档以及始终保持最新的系统架构图。

本地开发仪表板

值得一提的是,尽管 Encore 具有很多功能,但它却没有npm 依赖项

霍诺

Hono是由Yusuke Wada创建的。他于 2021 年启动了这个项目,因为当时没有能够在Cloudflare Workers上运行良好的 Node.js 框架。此后,Hono 增加了对许多其他运行时的支持,例如 Node.js、Bun 和 Deno。

import { Hono } from 'hono'
const app = new Hono()

app.get('/', (c) => c.text('Hono!'))

export default app
Enter fullscreen mode Exit fullscreen mode

Hono 非常小巧, hono/tiny 预设大小不到 13kB,非常适合部署到 Cloudflare Workers。此外,Hono 还完全没有NPM 依赖,这真的令人印象深刻!

运行时的卖点很有意思,无论使用哪种 JavaScript 运行时,你都可以运行 Hono。在他们的代码库中,有一个适配器的概念,你可以看到他们针对每个运行时所做的调整。我认为这对应用的采用和用户群的增长至关重要,但实际上,对于个人用户来说,一旦将应用部署到云端,你可能不会再切换运行时。

尽管 Hono 轻量级,但它内置了大量的中间件,包括第一方和第三方的,您可以安装它们来增强您的应用。这种“需要用的时候再添加”的做法在 Express 中很流行。如果您的应用规模较小,这种方法效果很好;但对于规模较大的应用来说,维护大量的依赖项列表可能会令人沮丧。

艾丽西亚

Elysia 与 Encore 类似,都是为 TypeScript 构建的,并且在 API 处理程序中提供了类型安全。了解 API 处理程序内部的操作可以节省大量时间,而且无需在代码中反复进行类型检查,这一点非常棒。

您可以使用模块指定请求类型,该模块是TypeBox 验证库t的扩展。与 Encore 不同,验证发生在 JavaScript 层,这会增加一些性能开销。

import { Elysia, t } from 'elysia'

new Elysia()
  .patch("/profile", ({ body }) => body.profile, {
    body: t.Object({
      id: t.Number(),
      profile: t.File({ type: "image" }),
    }),
  })
  .listen(3000);
Enter fullscreen mode Exit fullscreen mode

添加Swagger文档只需一行代码,并且 Elysia 拥有对OpenTelemetry的第一方支持。这非常好,因此无论使用哪个平台,您都可以轻松监控您的应用程序。

Elysia 很快!但不如 Encore 快,下一节你会看到。

Nest.js

Nest.js 与本次比较中的其他框架略有不同。Encore、Elysia 和 Hono 致力于提供极简的 API 来创建端点和中间件,您可以自由地构建业务逻辑。Nest.js 则更加固执己见,强制您以特定的方式构建代码。它提供了一种模块化架构,将代码组织成不同的抽象,例如提供程序、控制器、模块和中间件。

Nest 旨在简化大型应用程序的维护和开发。但您是否喜欢 Nest 提供的自洽结构,最终取决于您的主观感受。我认为,对于大型项目来说,它或许更具优势,因为这些项目的长期可维护性比速度和简洁性更重要。对于只有少数开发人员的小型项目来说,增加抽象级别在大多数情况下可能有些过度。与 Hono、Encore 和 Elysia 相比, Nest 自洽的本质也带来了更陡峭的学习曲线。

很难学

使用 Nest 时,您可以选择使用Express 或 Fastify作为底层 HTTP 服务器框架。所有 Nest 功能均基于此框架添加。

表现

在选择框架时,速度或许并非最重要的因素,但却不容忽视。它会影响你的应用响应速度,并最终影响你的托管费用。

速度

我们对启用和禁用请求模式验证的情况进行了基准测试,测量单位是每秒请求数。括号中的名称是所使用的请求验证库。Encore.ts 已内置请求验证功能。

基准

Encore.ts 在我们的基准测试中是所有框架中速度最快的,其次是 Elysia、Hono、Fastify 和 Express。Nest 的底层使用了 Fastify 或 Express,因此您可以预期 Nest 应用的性能会与之相当,但由于 Nest 增加了一些开销,因此速度可能会更慢。

Encore.ts 为何速度如此之快?秘诀在于 Encore.ts 拥有Rust 运行时。而 Rust 速度很快!

Encore.ts 实际上由两部分组成:

  1. 面向用户的 TypeScript 部分,用于定义 API 和基础设施。

  2. 在底层,它有一个用 Rust 编写的多线程运行时。

提升性能的关键是将尽可能多的工作从单线程 Node.js 事件循环转移到 Rust 运行时。

例如,Rust 运行时处理所有输入/输出,例如接受传入的 HTTP 请求或从数据库读取数据。请求或数据库查询完全处理后,就会移交给 Node.js 事件循环。

代码结构

Hono、Elysia 和 Encore 对代码结构没有硬性要求。而且,这些框架创建 API 和中间件的方式也相当相似。

以下是每个框架的 GET 端点。当然,它们之间也存在一些差异,但如果我们仔细观察,你会发现这些 API 相当相似。至少在我看来,相似程度足以让这一点成为决定性因素:

安可

interface Response {
  message: string;
}

export const get = api(
  { expose: true, method: "GET", path: "/hello/:name" },
  async ({ name }: { name: string }): Promise<Response> => {
    const msg = `Hello ${name}!`;
    return { message: msg };
  },
);
Enter fullscreen mode Exit fullscreen mode

艾丽西亚

import { Elysia, t } from "elysia";

new Elysia()
  .get(
    "/hello/:name",
    ({ params }) => {
      const msg = `Hello ${params.name}!`;
      return { message: msg };
    },
    {
      response: t.Object({
        message: t.String(),
      }),
    },
  )
Enter fullscreen mode Exit fullscreen mode

霍诺

import { Hono } from "hono";

const app = new Hono();

app.get("/hello/:name", async (c) => {
  const msg = `Hello ${c.req.param("name")}!`;
  return c.json({ message: msg });
});
Enter fullscreen mode Exit fullscreen mode

真正重要的是,在构建健壮的应用程序时能够依赖类型安全。Encore 和 Elysia 提供了类型安全的 API,但 Encore 在使用 Pub/Sub 等基础设施时也提供了编译时类型安全。使用 Encore,在调用其他服务中的端点时也能获得编译时类型安全。如果您曾经使用过微服务架构,您就会明白这有多重要。

类型安全

Nest.js 在 API 设计方面非常突出。Nest 应用中包含了大量的概念和抽象。这既是好事也是坏事,具体取决于你的个人偏好。当你浏览 Nest 应用时,你首先会注意到的一点就是它对装饰器的使用。Nest 严重依赖装饰器,例如在使用依赖注入将服务注入到控制器时。

Nest 控制器

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}
Enter fullscreen mode Exit fullscreen mode

就我个人而言,我并不是一个狂热粉丝,而且我知道我不是唯一一个这样的人。

部署和基础设施

所有这些框架都类似,因为它们可以部署到所有主流云平台(如 Digital Ocean 和 Fly.io)或直接部署到 AWS 或 GCP 等云提供商。

Encore提供自动化的本地基础设施。encore run启动您的应用并启动所有本地基础设施,例如数据库和 Pub/Sub 主题。告别 YAML、Docker Compose 以及常见的麻烦。

再来一次

构建 Encore 应用程序时,您会获得一个运行时配置,您可以在其中提供连接到云中基础设施所需的配置。

如果您想快速将 Encore 应用迁移到云端,又不想自行部署,那么您可以使用Encore Cloud。Encore Cloud 提供 CI/CD 和预览环境,方便您提交拉取请求。此外,如果您愿意,Encore Cloud 还可以在您自己的 AWS 或 GCP 云中配置所有必要的基础设施。这意味着您的应用不依赖任何第三方服务,您可以完全掌控所有基础设施。

Hono 的优势在于它支持多种不同的运行时,因此在部署方面拥有丰富的选择。部署到 Cloudflare Workers、Netlify 或 AWS Lambda 非常简单,无需大量配置。

使用Nest,您可以运行nest build将 TypeScript 代码编译为 JavaScript 的命令。此过程会生成一个 dist 包含编译文件的目录。差不多就是这样,然后您可以使用 Node.js 运行该dist文件夹。

部署Elysia应用的推荐方法是使用命令将应用编译为二进制文件bun build。编译完成后,无需 Bun 在计算机上安装即可运行服务器。

总结

就是这样!希望你知道下一个项目该用什么框架。

如果您想了解有关 Encore.ts 的更多信息,可以查看 GitHub 上的开源项目:https://github.com/encoredev/encore

建议:

文章来源:https://dev.to/encore/nodejs-frameworks-roundup-2024-elysia-hono-nest-encore-which-should-you-pick-19oj
PREV
🎉32 个面向视觉学习者的代码教程🖼
NEXT
如何让 ChatGPT 调用应用中的函数