阿川私房教材:學程式,拿 offer!

63 個專案實戰,直接上手!
無需補習,按步驟打造你的面試作品。

立即解鎖你的轉職秘笈

Node.js Web 框架-我們從哪裡開始?有這麼多的選擇,為您的專案選擇合適的一個可能會讓人感到不知所措。

在這篇文章中,我將帶您了解 Node.js 生態系統中最熱門的框架,詳細介紹每個框架的優點、缺點和最佳用例。

無論您追求的是速度、可擴展性還是簡單性,希望我們都能涵蓋所有內容,因此到最後,您將確切地知道哪個框架適合您。

我們將要關注的框架是: NestElysiaEncore.tsHono

影片版本:

{% 嵌入 https://www.youtube.com/watch?v=SEXpJbmab08 %}

開始了!

功能概述

從最輕量級到功能最豐富的範圍,我將框架定位如下:

功能概述

這並不意味著輕量級不好,它只是取決於您的專案的需求。 Hono的輕量級本質實際上是其賣點之一,其大小不到 14KB,非常適合部署到 Cloudflare Workers。

另一方面, Encore.ts具有許多內建功能,例如開箱即用的自動追蹤和本地基礎架構。

讓我們來看看每個框架,我們將從 Encore.ts 開始

安可.ts

一個開源框架,旨在更輕鬆地使用 TypeScript 建立健全且類型安全的後端。該框架有許多內建工具,可以讓您的開發體驗更加流暢,效能更佳,在本次比較中,它是所有框架中速度更快的

<

表>

<td><a href="https://encore.dev/docs/ts/primitives/apis" class="link-brandient">Type-safe API schemas</a></td>
<td><a href="https://encore.dev/docs/ts/develop/cors" class="link-brandient">CORS handling</a></td>
<td><a href="https://encore.dev/docs/ts/develop/logging" class="link-brandient">Structured logging</a></td>
<td><a href="https://encore.dev/docs/ts/develop/auth" class="link-brandient">Authentication</a></td>
<td><a href="https://encore.dev/docs/ts/primitives/pubsub" class="link-brandient">Pub/Sub integrations</a></td>
<td><a href="https://encore.dev/docs/ts/primitives/secrets" class="link-brandient">Secrets management</a></td>
<td><a href="https://encore.dev/docs/deploy/infra" class="link-brandient">Infrastructure integrations</a></td>
<td><a href="https://encore.dev/docs/ts/primitives/databases" class="link-brandient">Database integrations</a></td>
<td><a href="https://encore.dev/docs/observability/encore-flow" class="link-brandient">Architecture Diagrams</a>
</td>
<td><a href="https://encore.dev/docs/observability/dev-dash" class="link-brandient">Local Development Dashboard</a>
</td>
<td><a href="https://encore.dev/docs/develop/api-docs" class="link-brandient">Service Catalog</a></td>
<td><a href="https://encore.dev/docs/ts" class="link-brandient">TypeScript native</a></td>
<td><a href="https://encore.dev/docs/ts/develop/debug" class="link-brandient">Debugging</a></td>
<td><a href="https://encore.dev/docs/ts/develop/errors" class="link-brandient">Error handling</a></td>
<td><a href="https://encore.dev/blog/event-loops" class="link-brandient">Multithreading</a></td>
<td><a href="https://encore.dev/blog/event-loops" class="link-brandient">Request validation</a></td>
<td><a href="https://encore.dev/docs/observability/tracing" class="link-brandient">Tracing</a></td>
<td><a href="https://encore.dev/docs/develop/client-generation" class="link-brandient">API Client generation</a>
</td>
<td><a href="https://encore.dev/docs/deploy/infra" class="link-brandient">Automatic local infrastructure</a></td>
<td><a href="https://encore.dev/docs/ts/develop/testing" class="link-brandient">Automated testing</a></td>

Encore 具有內建的請求驗證。您在常規 TypeScript 中定義的請求和回應類型用於在編譯和執行時驗證請求。與其他框架不同的是,實際的驗證是在 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"};
  },
);

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!"
});

使用 Encore.ts,您可以將基礎架構集成為應用程式程式碼中的類型安全性物件。建立資料庫或 Pub/Sub 主題只需要幾行應用程式程式碼。 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.

建立 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({ ... });

Encore 還配備了一個內建的開發儀表板。當您啟動 Encore 應用程式時,開發儀表板可在連接埠localhost:9400上使用。從這裡您可以呼叫端點,有點像 Postman。對應用程式的每次呼叫都會產生一個跟踪,您可以檢查該跟踪以查看 API 請求、資料庫呼叫和 Pub/Sub 訊息。本地開發儀表板還包括自動 API 文件始終最新的系統架構圖

本地發展儀表板

{% 嵌入 https://www.youtube.com/watch?v=Da\_jHj6bLac %}

值得一提的是,儘管 Encore 具有許多功能,但它的npm 依賴項為 0

連接

Hono和田佑介的創作。他在 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

Hono 非常小, hono/tiny預設不到 13kB,這使得它非常適合部署到 Cloudflare Workers。 Hono 還具有0 個 NPM 依賴項,這確實令人印象深刻!

多執行時的賣點很有趣,無論 Javascript 執行時如何,你都可以執行 Hono。在他們的存儲庫中,他們有適配器的概念,您可以在其中看到他們為每個執行時所做的調整。我認為這對於採用和擴大用戶群來說是巨大的,但實際上對於個人用戶來說,一旦將應用程式部署到雲端中,您可能不會切換執行時。

儘管 Hono 是輕量級的,開箱即用,但它有一堆中間件,包括第一方和第三方,您可以安裝它們來增強您的應用程式。這是在 Express 中流行的「當你想使用它時加入它」的方法。只要您的應用程式很小,這就可以很好地工作,但對於較大的應用程式,維護大量依賴項可能會令人沮喪。

艾莉西亞

Elysia 與 Encore 一樣,是為 TypeScript 建置的,並且還在 API 處理程序中提供類型安全性。了解 API 處理程序中正在使用的內容可以為您節省大量時間,而且不必在程式碼中進行類型檢查,這非常好。

您可以使用t模組指定請求類型,該模組是TypeBox 驗證庫的擴充。與 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);

新增Swagger文件僅需要一行程式碼,且 Elysia 擁有對OpenTelemetry的第一方支援。這真的很好,因此無論平台如何,您都可以輕鬆監控您的應用程式。

艾莉西亞的速度很快!但不如 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 看起來非常相似。至少夠相似,在我看來這不是決定因素:

安可.ts

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 };
  },
);

艾莉西亞

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(),
      }),
    },
  )

連接

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 });
});

真正重要的是在建立健壯的應用程式時能夠依賴類型安全。 Encore 和 Elysia 提供類型安全的 API,但 Encore 在使用 Pub/Sub 等基礎架構時也提供編譯時類型安全性。使用 Encore,您還可以在呼叫另一個服務中的端點時獲得編譯時類型安全性。如果您曾經使用過微服務架構,那麼您就會知道這有多大。

類型安全

Nest.js 是在 API 設計方面真正脫穎而出的一個。 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();
  }
}

就我個人而言,我並不是一個超級粉絲,而且我知道我不是唯一的粉絲。

部署和基礎設施

所有這些框架的相似之處在於它們都可以部署到所有主流雲端平台(例如 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/nestjs-vs-encorets-choosing-the-right-framework-for-your-typescript-microservices-1g61 %}

{% 嵌入 https://dev.to/encore/how-to-deploy-a-backend-application-to-digitalocean-using-docker-and-encore-1eh0 %}

{% 嵌入 https://dev.to/encore/choosing-the-right-tech-stack-a-developers-decision-making-guide-5gkd %}


原文出處:https://dev.to/encore/nodejs-frameworks-roundup-2024-elysia-hono-nest-encore-which-should-you-pick-19oj


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。

阿川私房教材:學程式,拿 offer!

63 個專案實戰,直接上手!
無需補習,按步驟打造你的面試作品。

立即解鎖你的轉職秘笈