」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > NestJS 與 Encore.ts:為您的 TypeScript 微服務選擇正確的框架

NestJS 與 Encore.ts:為您的 TypeScript 微服務選擇正確的框架

發佈於2024-11-09
瀏覽:657

Introduction

When web applications grow larger, so does the complexity in developing and maintaining the system. A common way to solve this issue is by using the microservice architecture, where developers break down systems into smaller well-managed components that can be individually managed and scaled.

To do this effectively, it’s often helpful to use a microservice framework. But choosing the right framework that natively supports microservices can be challenging. In this article, we are going to take a look at Encore.ts and Nest.js as the two relevant alternatives, since they both natively support microservices architectures and TypeScript.

Encore.ts is a newer open-source framework that stands out for its high performance, type-safety, and observability features. Nest.js on the other hand leads the TypeScript framework for building Microservices applications. Each of them has something strong to offer, so we will examine each framework in terms of architecture, performance, and scalability and explain how to determine which might work best for you.

Before we begin, let’s look at the benchmark data in the image below:

NestJS vs Encore.ts: Choosing the Right Framework for Your TypeScript Microservices

The benchmark data shows that Encore.ts can handle 121,005 requests per second without validation and 107,018 with schema validation. That’s significantly faster than traditional frameworks. For example, Express.js with Zod only hits about 15,707 requests per second without validation and 11,878 with it. So, Encore.ts is roughly 9 times quicker than Express, which Nestjs is built on.

Overview of Encore.ts and NestJS

When you’re starting a project, you want a framework that’s not only powerful but also easy for developers to use. Encore.ts and NestJS stands out when it comes to Microservice frameworks that has built-in support for Typescript, but they work in their own distinct ways.

Encore.ts is an open-source cloud-native framework designed for backend development with built-in infrastructure automation. It allows you to build modular distributed systems using declarative infrastructure libraries.

NestJS vs Encore.ts: Choosing the Right Framework for Your TypeScript Microservices

Encore.ts operates on a Rust runtime ****integrated with Node.js via napi for exceptional performance in handling I/O and multithreading while letting you write logic in TypeScript.

Here’s a simple example of how you can define a service in Encore.ts:

import { Service } from "encore.dev/service";

export default new Service("hello");

When this hello service is created, Encore.ts automatically treats the entire directory as part of the service—no extra configuration is needed.

On the other hand, NestJS has its own style. It’s a flexible TypeScript framework that lets you fully control how you build your app, giving you the freedom to structure things your way.

NestJS vs Encore.ts: Choosing the Right Framework for Your TypeScript Microservices

While it doesn’t handle infrastructure automation, NestJS makes it easy to integrate with nearly any third-party library, which opens up a lot of possibilities for different projects.

Here’s a look at how you could define a similar service in NestJS:

import { Controller, Get } from '@nestjs/common';

@Controller('hello')
export class HelloWorldController {
  @Get()
  sayHello(): string {
    return 'Hello, World!';
  }
}

NestJS offers you more flexibility but without the built-in automation found in Encore.ts.

Architecture and Design

The architecture of a framework dictates how your application is built and maintained over time. Both Encore.ts and NestJS are robust, but their core philosophies differ.

Encore.ts is opinionated and *cloud-first, making it ideal for large type-safe *distributed systems with many microservices. One of its standout features is native support for Pub/Sub, enabling event-driven architecture seamlessly.

Here's how you might define an event-driven service in Encore.ts using Pub/Sub:

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

// Define the event type for order creation
export interface OrderCreatedEvent {
    orderId: string;
}

// Create a topic for order creation events
export const orders = new Topic("orders", {
    deliveryGuarantee: "at-least-once",
});

// Create a subscription to listen for the order creation event
export const _ = new Subscription(orders, "process-order", {
    handler: async (event: OrderCreatedEvent) => {
        console.log('Order created:', event.orderId);
    },
});

NestJS, while capable of supporting microservices and event-driven architectures, offers a more modular approach. Its core follows the MVC pattern, and it allows developers to build systems their way by providing greater control over configurations.

For example, here is how you can define a services and events in NestJS with a far more modularized approach:

// order.event.ts
export class OrderCreatedEvent {
  constructor(public readonly order: Order) {}
}

// order.repository.ts
@Injectable()
export class OrderRepository {
  async save(order: Order): Promise {
    // Persistence logic
  }
}

// order.service.ts
@Injectable()
export class OrderService {
  constructor(
    private readonly orderRepository: OrderRepository,
    private readonly eventEmitter: EventEmitter2
  ) {}

  async createOrder(orderDto: CreateOrderDto): Promise {
    const order = new Order(orderDto);

    const savedOrder = await this.orderRepository.save(order);

    this.eventEmitter.emit(
      'order.created',
      new OrderCreatedEvent(savedOrder)
    );

    return savedOrder;
  }
}

// order.listener.ts
@Injectable()
export class OrderEventListener {
  @OnEvent('order.created')
  async handleOrderCreatedEvent(event: OrderCreatedEvent) {
    // Handle event logic separately
  }
}

// order.module.ts
@Module({
  imports: [EventEmitterModule.forRoot()],
  providers: [
    OrderService,
    OrderRepository,
    OrderEventListener
  ],
  exports: [OrderService]
})
export class OrderModule {}

By design, NestJS grants a lot of control over how components will interact, but the downside is much more boilerplate and you will also have to manage the infrastructure configurations yourself.

Built-in Features and Extensibility

In the development of distributed systems, the features provided by the framework will often facilitate development at the risk of introducing over-complexity.

Encore.ts standout feature is that it provides ways of automating infrastructure provisioning, both in local development and in cloud environments. This includes databases, Pub/Sub, cron jobs, and more. Encore.ts also provides a local development dashboard that auto-generates API documentation, architecture diagrams, and distributed tracing. It also generates the frontend clients, including OpenAPI spec support for REST APIs, which can be a big time saver for developer.

Here is an example of defining a REST API in Encore.ts, which also automatically generates the OpenAPI documentation:

import { api } from "encore.dev/api";

interface CreateOrderParams {
  productId: string;
  quantity: number;
}

interface OrderResponse {
  orderId: string;
  message: string;
}

export const createOrder = api(
  { method: "POST", path: "/orders", expose: true, auth: true },
  async (params: CreateOrderParams): Promise => {
    const orderId = "order123";
    return {
      orderId,
      message: `Order created for product ${params.productId} with quantity ${params.quantity}.`,
    };
  }
);

With Encore.ts, the moment you define your service, documentation and diagrams are automatically available without additional setup.

NestJS vs Encore.ts: Choosing the Right Framework for Your TypeScript Microservices

NestJS has been popular due to its flexibility. From day one, it supports REST, GraphQL, and WebSocket with ease, but the main thing behind its popularity is that it easily connects with third-party libraries.

For example, if you want to add GraphQL support, it’s a simple process.

import { Resolver, Query, Mutation, Args } from '@nestjs/graphql';

// Define a simple model for an order (this will be your GraphQL type)
class Order {
  id: string;
  product: string;
  quantity: number;
}

// Resolver to handle GraphQL queries and mutations
@Resolver(() => Order)
export class OrderResolver {
  // Array to store orders (simulating a database)
  private orders: Order[] = [];

  // Query to get all orders
  @Query(() => [Order], { name: 'getAllOrders' })
  getAllOrders(): Order[] {
    return this.orders;
  }

  // Mutation to create an order
  @Mutation(() => Order)
  createOrder(
    @Args('product') product: string,
    @Args('quantity') quantity: number,
  ): Order {
    const newOrder = { id: Date.now().toString(), product, quantity };
    this.orders.push(newOrder);
    return newOrder;
  }
}

NestJS makes it simple to build on its core features, but it doesn’t offer the same level of automated infrastructure and features as Encore.ts does.

Performance and Scalability

Performance is critical when building distributed systems, especially at scale.

Encore.ts is built for high performance with its Rust runtime, which handles I/O operations and multithreading efficiently. Rust’s speed and memory safety give Encore.ts a significant advantage over purely Node.js based frameworks. In terms of scalability, Encore.ts is cloud-native and can autoscale using serverless architecture or Kubernetes, depending on your deployment strategy.

NestJS, on the other hand, is more traditional in how it handles performance and scalability. Because NestJS is purely TypeScript and JavaScript-based, it relies on the performance optimizations you apply during setup. Scaling a NestJS app typically involves manually configuring Kubernetes, Docker, or serverless platforms like AWS Lambda.

While NestJS offers flexibility in how you scale, the configuration requires more manual effort than Encore.ts’s built-in automation.

Let’s understand the difference in performance between encore.ts and Nest.js from the benchmark data in the image below:

NestJS vs Encore.ts: Choosing the Right Framework for Your TypeScript Microservices

From the benchmark data, encore.ts stands out when it comes to performance, with a start time of just 8.3 milliseconds, while NestJS takes about 143.7 milliseconds, making it nearly nine times faster than traditional frameworks.

Deployment Strategies

How you deploy your application is a key consideration for any project, especially when thinking about cloud environments.

Encore.ts offers an easy path to deployment through its open-source tools or the Encore Cloud Platform. Using the open-source version, you can use encore build to build your project and create a Docker image, which can then be deployed anywhere Docker is supported:

encore build docker --services=service1,service2 --gateways=api-gateway MY-IMAGE:TAG

This creates a Docker image that can be deployed anywhere.

Alternatively, if you opt to use the Encore Cloud Platform, it automates the entire CI/CD pipeline, deploying directly to your own cloud on AWS or GCP with serverless or Kubernetes options.

NestJS vs Encore.ts: Choosing the Right Framework for Your TypeScript Microservices

In contrast, NestJS requires manual setup for deployment. Typically, developers use Docker to containerize NestJS applications and deploy them to a cloud provider of their choice. While this gives you control over your deployment strategy, it requires more configuration—even for a simple application you need to go through many steps:

  1. Create a Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "run", "start:prod"]
  1. Create a docker-compose.yml file:
version: '3.8'
services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:pass@db:5432/myapp
    depends_on:
      - db
  db:
    image: postgres:13
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=myapp
  1. Create GitHub Actions workflow for NestJS
name: Deploy NestJS
on:
  push:
    branches: [ main ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Build and push Docker image
        run: |
          docker build -t myapp .
          docker push myregistry/myapp:latest
      - name: Deploy to cloud
        run: |
          # Add your cloud deployment commands here, e.g., kubectl apply, AWS ECS deploy, etc.

The larger your application becomes, and the more need you have for multiple staging and testing environments, the more burdensome this manual configuration approach becomes—continuously growing in terms of time spent on maintenance.

Use Case Considerations

When choosing between Encore.ts and NestJS, the decision should be based on the specific needs of your project.

Encore.ts is perfect for cloud-first applications and large distributed systems that benefit from built-in automation. It's Rust-powered runtime and infrastructure management makes it ideal for event-driven architectures, microservices, and high-performance applications. Encore’s fast growing community is a reliable source of support and finding ways of integrating third-party tools.

On the other hand, NestJS shines when flexibility and customization are needed. It’s well-suited for enterprise apps that require fine-grained control over every aspect, and where spending time on manual configuration is acceptable. NestJS’s relatively extensive ecosystem and community support make it easier to find resources and third-party tools.

Conclusion

Choosing between Encore.ts and NestJS comes down to your project’s specific needs.

If you’re looking for a simple, high-performance, cloud-native framework with built-in automation, Encore.ts is an excellent choice. It streamlines the development of distributed systems by managing infrastructure automatically, and its Rust-powered performance is hard to beat.

However, if you need a very flexible, modular framework that gives you control over every minute aspect, NestJS is probably the way to go. Its extensibility and large ecosystem make it a solid choice for custom enterprise solutions.

Both frameworks are powerful in their own right, and the best choice depends on whether you value performance and simplicity, or full flexibility and control.

Next steps

If performance and simplicity matters to your project, it might be a good idea to try out Encore.ts. And it's all Open Source, so you can check out the code and contribute on GitHub.

版本聲明 本文轉載於:https://dev.to/encore/nestjs-vs-encorets-choosing-the-right-framework-for-your-typescript-microservices-1g61?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • `useCallback` 與 `useMemo` 掛鉤
    `useCallback` 與 `useMemo` 掛鉤
    提升 React 效能:useCallback 與 useMemo Hooks React 的 useCallback 和 useMemo 掛鉤對於優化應用程式的效能至關重要。了解何時以及如何使用它們可以使您避免不必要的重新渲染並確保您的應用程式順利運行。在本文中,我們將深入研究有...
    程式設計 發佈於2024-11-09
  • PHP 中的多重繼承
    PHP 中的多重繼承
    繼承:繼承是物件導向程式設計(OOP)中的一個基本概念,它允許類別從其他類別繼承屬性和行為。它是一種基於現有類別創建新類別、促進程式碼重用以及在類別之間建立層次關係的機制。 繼承是基於「父子」或「超類別-子類別」關係的概念。另一個類別繼承自的類別稱為超類別或基底類,而從超類別繼承的類別稱為子類別或衍...
    程式設計 發佈於2024-11-09
  • jQuery 如何簡化 JSON 資料到 HTML 表的轉換?
    jQuery 如何簡化 JSON 資料到 HTML 表的轉換?
    jQuery 的JSON 到HTML 表格轉換的簡化方法將JSON 陣列轉換為HTML 表格可能是一項繁瑣的任務,但jQuery 簡化了這個過程要從JSON 陣列產生表,請使用getJSON() 函數檢索資料:$.getJSON(url , function(data) {接下來,建立表格主體:va...
    程式設計 發佈於2024-11-09
  • 如何從 Node.js 中的大型 Firebase 資料集中有效率地檢索隨機乘積?
    如何從 Node.js 中的大型 Firebase 資料集中有效率地檢索隨機乘積?
    如何在 Node Firebase 中檢索唯一的隨機乘積? Firebase 提供靈活的資料結構,讓您以分層方式儲存資料。在某些情況下,您可能擁有大量記錄,但只需要一筆唯一且隨機的記錄。本文將引導您透過兩種方法在 Node Firebase 中實現此目的。 經典方法:下載所有記錄假設您的資料庫結構類...
    程式設計 發佈於2024-11-09
  • PHP 中的 session_unset() 和 session_destroy() 有什麼不同?
    PHP 中的 session_unset() 和 session_destroy() 有什麼不同?
    深入探討PHP 中session_unset() 和session_destroy() 之間的差異使用PHP 會話時,開發人員通常必須在函數session_unset() 和session_destroy()。儘管聽起來相似,但這些函數表現出顯著的差異。 功能差異雖然這兩個函數都會影響會話變量,但它...
    程式設計 發佈於2024-11-09
  • 如何在 JavaScript 中組合陣列並同時儲存唯一元素?
    如何在 JavaScript 中組合陣列並同時儲存唯一元素?
    在JavaScript 中將數組與唯一元素組合要基於唯一項合併數組,您可以利用以下技術:var newCells = []; for (var i = 0; i < totalCells.length; i ) { var lineNumber = totalCells[i].lin...
    程式設計 發佈於2024-11-09
  • 將日期物件轉換為時間戳記時,一元加運算子有何作用?
    將日期物件轉換為時間戳記時,一元加運算子有何作用?
    Unary Plus:將日期物件轉換為毫秒時間戳在JavaScript 中,您可能會遇到類似以下內容的程式碼:function fn() { return new Date; }此表達式傳回表示當前時間的時間戳,而不是完整的 Date 物件。然而,加號 ( ) 的作用並不是立即顯而易見。 答案...
    程式設計 發佈於2024-11-09
  • 如何消除 Mac 版 Chrome 中不需要的「過度滾動」?
    如何消除 Mac 版 Chrome 中不需要的「過度滾動」?
    克服網頁中的「過度滾動」在Mac 版Chrome 中,「過度滾動」是一種不良效果,它允許用戶將頁面拖到其正常查看區域之外,如所提供的影像所示。若要解決此問題並改善使用者體驗,請考慮以下兩種方法:方法一:限制過度捲動如果要完全停用過度捲動,請使用下列CSS 程式碼: html { overfl...
    程式設計 發佈於2024-11-09
  • ## 為什麼 JQuery 的 `load()` 函數在不同瀏覽器中表現不同?
    ## 為什麼 JQuery 的 `load()` 函數在不同瀏覽器中表現不同?
    Jquery load() 跨瀏覽器的不一致Jquery load() 跨瀏覽器的不一致在嘗試深入研究JQuery 和AJAX 時,開發人員可能會遇到一個特殊的問題,其中load( ) 函數在不同瀏覽器中表現出不一致的行為。具體來說,在提供的程式碼片段中,load()函數用於將list1.html的...
    程式設計 發佈於2024-11-09
  • 為什麼我在 Go 中收到「語法錯誤:Else 之前出現意外的分號」?
    為什麼我在 Go 中收到「語法錯誤:Else 之前出現意外的分號」?
    Go 中 Else 之前意外的分號:詳細解釋你的 Go 碼在第 21 行遇到異常錯誤:「syntax error:unexpected其他之前的分號或換行符。 這裡的核心問題源自於Go的自動分號插入規則。通常,Go 中分號是可選的;但是,編譯器會自動將它們插入到某些行的末尾以保持語法完整性。其中一個...
    程式設計 發佈於2024-11-09
  • 如何防止 Apache 快取 CSS 檔案並確保顯示最新版本?
    如何防止 Apache 快取 CSS 檔案並確保顯示最新版本?
    使用Apache 防止伺服器端CSS 檔案快取開發網站時,確保訪客存取最新版本至關重要用於防止快取問題的CSS 文件。本文解決了 Apache 是否快取資源的問題,並提供了防止其這樣做的解決方案,特別是遇到儘管重新載入頁面但 CSS 變更未反映在瀏覽器中的場景時。 是Apache 真的會快取資源嗎?...
    程式設計 發佈於2024-11-09
  • 您應該使用哪種 MySQL 整數資料類型?
    您應該使用哪種 MySQL 整數資料類型?
    了解MySQL 整數資料類型之間的差異MySQL 提供了一系列整數資料類型,它們的儲存需求和值範圍各不相同。這些類型包括tinyint、smallint、mediumint、bigint 和int。了解它們之間的差異對於為您的特定資料需求選擇適當的資料類型至關重要。 資料大小和範圍注意​​事項這些資...
    程式設計 發佈於2024-11-09
  • 為什麼我在 JavaScript 的輸入值為空?
    為什麼我在 JavaScript 的輸入值為空?
    輸入值與變數儲存:為什麼會陷入空困境? 當嘗試使用 JavaScript 從輸入欄位檢索值時,開發人員經常遇到如果資料儲存在變數中,則為空值。這個令人費解的問題可能源自於 Web 開發的非同步特性以及瀏覽器執行程式碼的方式。 在 JavaScript 中,執行腳本時會擷取輸入欄位的初始值。如果稍後在...
    程式設計 發佈於2024-11-09
  • 如何使用 RequestAnimationFrame 來穩定動畫的幀速率 (FPS)?
    如何使用 RequestAnimationFrame 來穩定動畫的幀速率 (FPS)?
    RequestAnimationFrame Fps 穩定RequestAnimationFrame (rAF) 已在動畫中變得流行,可提供流暢且高效的執行。然而,控制幀速率 (FPS) 以確保一致性可能具有挑戰性。 將 rAF 限制為特定 FPS要將 rAF 限制為特定 FPS,您可以自上一幀執行以...
    程式設計 發佈於2024-11-09
  • 適合初學者的關鍵 Python 術語
    適合初學者的關鍵 Python 術語
    您是否曾经在与程序员交谈时,因不熟悉的行话而感到茫然?或者,也许您是 Python 编程的初学者,并且遇到了某些您不完全理解的术语。学习Python中使用的常用术语不仅可以帮助你更专业地解释你的代码,还可以让你更轻松地跟上讨论。本文通过简单的解释、用例和示例探讨了基本的 Python 术语,以帮助您...
    程式設計 發佈於2024-11-09

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3