Fundamentals

平台无关性

了解 Nest 的平台无关性设计,如何在不同的 HTTP 平台(Express、Fastify)之间切换,以及如何构建平台无关的应用程序

平台无关性

Nest 是一个平台无关的框架。这意味着您可以开发可重用的逻辑部分,这些部分可以在多种不同类型的应用程序中使用。例如,大多数组件可以在不同的底层 HTTP 服务器框架(例如 Express 和 Fastify)之间重用而无需更改,甚至可以跨不同类型的应用程序(例如,HTTP 服务器框架、具有不同传输层的微服务和 Web Sockets)重用。

一次构建,随处使用

文档的概述部分主要展示了使用 HTTP 服务器框架(例如,提供 REST API 或提供 MVC 风格的服务器端渲染应用程序)的编码技术。然而,所有这些构建块都可以在不同的传输层(微服务WebSockets)之上使用。

此外,Nest 还提供了专用的 GraphQL 模块。您可以将 GraphQL 用作 API 层,与提供 REST API 的方式交替使用。

最后,应用程序上下文功能有助于在 Nest 之上创建任何类型的 Node.js 应用程序 - 包括 CRON 作业和 CLI 应用程序等。

Nest 致力于成为 Node.js 应用程序的全栈平台,为您的应用程序带来更高级别的模块化和可重用性。一次构建,随处使用!

平台适配器

为了实现平台独立性,Nest 使用平台适配器。适配器是一个主要职责是代理中间件和处理程序到适当的特定于库的实现的类。每个适配器封装了相应库的功能,以提供一个通用的接口。适配器使用 TypeScript 接口实现。重要的是,适配器启用平台独立性,但不强制它。

类型提示

虽然大多数代码是平台无关的,但有时您需要访问底层平台 API。每个平台适配器都公开了几个有用的类型提示,您可以在需要时使用它们来类型化您的声明。例如:

const app = await NestFactory.create<NestExpressApplication>(AppModule);

现在 app 对象具有专门用于 Express 平台的方法。请注意,您不需要指定类型,除非您实际想要访问底层平台 API。

库特定的步骤

要访问底层平台实例(例如,Express 或 Fastify),您需要使用平台特定的方法。

const app = await NestFactory.create(AppModule);

// app.getHttpAdapter() 或使用快捷方式 app.getHttpServer()
const httpAdapter = app.getHttpAdapter();

getHttpAdapter() 是一个返回底层框架使用的适配器的方法。在 Express 的情况下,它返回一个包装 Express 应用程序的适配器实例。然后您可以使用此适配器实例来操作底层实例。

const app = await NestFactory.create(AppModule);
const httpAdapter = app.getHttpAdapter();

const expressInstance = httpAdapter.getInstance();

getInstance() 方法返回底层的 Express 实例(对于 Fastify 平台,它返回 Fastify 实例)。

平台特定的包

请记住,当您想要利用底层平台的特定功能时,您的应用程序变得平台相关。例如,要访问 Express 特定的功能,您需要安装 Express 类型包:

$ npm i --save-dev @types/express

Express 平台

Express 是一个众所周知的 Node.js 简约 Web 框架。它是一个经过实战测试、生产就绪的库,拥有大量由社区实现的资源。默认情况下使用 @nestjs/platform-express 包。许多用户都能很好地使用 Express,无需采取任何操作即可启用它。

const app = await NestFactory.create<NestExpressApplication>(AppModule);

Fastify 平台

Fastify 是一个高性能、低开销的框架,高度专注于提供最大效率和速度。阅读如何使用它这里

要使用 Fastify 平台,请选择内置的 FastifyAdapter

import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';

const app = await NestFactory.create<NestFastifyApplication>(
  AppModule,
  new FastifyAdapter()
);

默认情况下,Fastify 仅在 localhost 127.0.0.1 接口上监听(了解更多)。如果您想在其他主机上接受连接,您应该在 listen() 调用中指定 '0.0.0.0'

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );
  await app.listen(process.env.PORT ?? 3000, '0.0.0.0');
}
bootstrap();

平台特定的上下文

有时您可能想要访问对底层平台请求/响应对象的引用。每个平台都有不同的执行上下文。Nest 提供了一种访问这些对象的方法,通过 @Req()@Res() 装饰器。

import { Controller, Get, Req, Res } from '@nestjs/common';
import { Request, Response } from 'express';

@Controller('cats')
export class CatsController {
  @Get()
  findAll(@Req() request: Request, @Res() response: Response): string {
    // 平台特定的请求/响应对象
    return 'This action returns all cats';
  }
}

您还可以使用以下平台特定的装饰器:

装饰器对象
@Request(), @Req()req
@Response(), @Res()res
@Next()next
@Session()req.session
@Param(key?: string)req.params / req.params[key]
@Body(key?: string)req.body / req.body[key]
@Query(key?: string)req.query / req.query[key]
@Headers(name?: string)req.headers / req.headers[name]
@Ip()req.ip
@HostParam()req.hosts

为了与底层 HTTP 平台(例如,Express 和 Fastify)的类型兼容,Nest 提供了 @Res({ passthrough: true }) 装饰器。当您使用此装饰器时,您能够使用原生响应对象(例如,response.cookie()response.header()),但将其余部分留给 Nest。例如:

@Get()
findAll(@Res({ passthrough: true }) response: Response) {
  response.cookie('name', 'value');
  return [];
}

警告 禁止同时使用 @Res()@Response()return 语句。如果两者都被使用,标准方式对于该特定路由处理程序将被禁用,并且将不再按预期工作。要同时使用两者(例如,通过注入响应对象来仅设置 cookies/headers 但仍将其余部分留给框架),您必须在 @Res({ passthrough: true }) 装饰器中将 passthrough 选项设置为 true

性能

当涉及到性能时,Fastify 提供了更好的结果,产生的开销几乎是 Express 的两倍。公平地说,这并不意味着您的应用程序会慢两倍,因为它取决于您的应用程序的复杂性。一般来说,Fastify 可以每秒处理多达 30,000 个请求,而 Express 每秒处理 15,000 个请求。

提示 当使用 Fastify 时,请确保选择支持您正在使用的 Fastify 版本的包。