(一) 《Nest.js:渐进式node.js框架》 介绍

Nestjs 是一个构建在Node.js Express服务器之上的现代Web框架。利用现代ES6 JavaScript提供的强大灵活性和TypeScript在编译期间强制实现类型安全,将可扩展的Node.js服务器提高到一个全新的水平。Nest将三种不一样的技术结合为一个成功的组合,使应用程序高度可测试,可扩展,松散耦合和可维护:

  • 面向对象编程(OOP):围绕对象而不是行为和可重用性构建的模型。
  • 函数编程(FP):设计的函数不依赖于全局状态,即对于一些不改变的设置参数,函数f(x)每次都返回相同的结果。
  • 函数式响应型编程(FRP):扩展上面的FP和响应型编程。函数式响应型编程是其核心功能编程,它考虑了跨时间的流程。它在UI,模拟,机器人和其余应用程序中很是有用,其中特定时间段的结果可能与另外一个时间段的结果不一样。

主题讨论

1. Nest CLI

Nest的第5版中新增了一个CLI命令,容许经过命令行生成项目和文件。 全局安装CLI:javascript

npm install -g @nestjs/cli
复制代码

或者经过Docker:java

docker pull nestjs/cli:[version]
复制代码

可使用如下命令生成新的Nest项目:node

nest new [project-name]
复制代码

此过程将询问 name, description, version (defaults to 0.0.0), and author (你的名字)。 完成此过程后,您将拥有一个设置好的Nest项目,其中依赖项安装在 node_modules 文件夹。 new 命令还会询问你想用什么包管理器,以一样的方式,有 yarn 或 npm 能够用。web

CLI中最经常使用的命令是 generate (g) 命令, 容许你建立新的 controllers, modules, servies 或Nest支持的任何其它组件:docker

  1. class (cl)
  2. controller (co)
  3. decorator (d)
  4. exception (e)
  5. filter (f)
  6. gateway (ga)
  7. guard (gu)
  8. interceptor (i)
  9. middleware (mi)
  10. module (mo)
  11. pipe (pi)
  12. provider (pr)
  13. service (s)

括号中的字符串是该特定命令的别名 typescript

nest generate service [service-name]
复制代码

在控制台中,您能够输入:数据库

nest g s [service-name]
复制代码

最后,Nest CLI提供 info (i) 命令以显示项目的有关信息。这个命令将输出以下信息:npm

[System Information]
OS Version     : macOS High Sierra
NodeJS Version : v8.9.0
YARN Version    : 1.5.1
[Nest Information]
microservices version : 5.0.0
websockets version    : 5.0.0
testing version       : 5.0.0
common version        : 5.0.0
core version          : 5.0.0
复制代码

2.依赖注入

依赖注入是一种技术,它提供一个依赖对象,如一个模块或者一个组件,而后依赖的对象就像服务同样,能够把它注入到组件的构造函数中。 举个例子,在这里咱们将 UserRespository 服务注入到 UserService 的构造函数中, 从而提供从 UserService 组件内部访问User Database存储库的权限。编程

@Injectable()
export class UserService implements IUserService {
    constructor(@Inject('UserRepository') private readonly UserRepository: typeof User) { }
    ...
}
复制代码

而后,这个 UsersService 将被注入到 UsersController,将提供控制器的路由对 UsersService 访问。后续章节中会介绍路由和依赖注入的更多信息。api

3.认证

身份验证是开发过程当中最重要的方面之一。 做为开发人员,咱们始终但愿确保用户只能访问他们有权访问的资源。 近年来,身份验证方法已经扩展到变得更加复杂,但咱们仍然须要相同的服务器端逻辑,以确保这些通过身份验证的用户始终是合法用户,并将这种身份验证持久化,这样就不须要为每个 REST API 或 Websocket 的调用者从新进行身份验证,由于那将提供很是糟糕的用户体验。

Nest 选择集成Node.js生态系统中很是有名的认证库 Passport,同时使用JWT(JSON Web Token)策略。 Passport是在调用控制器上的端点以前传递HTTP调用的中间件。下面是为示例项目编写的 AuthenticationMiddleware ,它扩展了 NestMiddleware,根据请求有效负载中的电子邮件对每一个用户进行身份验证。

@Injectable()  
export class AuthenticationMiddleware implements NestMiddleware {  
   constructor(private userService: UserService) { }  

   async resolve(strategy: string): Promise<ExpressMiddleware> {  
       return async (req, res, next) => {  
           return passport.authenticate(strategy, async (/*...*/args: any[]) => {  
               const [, payload, err] = args;  
                if (err) {  
                    return res.status(HttpStatus.BAD_REQUEST).send('Unable to authenticate the user.');  
                }  

               const user = await this.userService.findOne({
                    where: { email: payload.email }
               });  
                req.user = user;  
                return next();  
            })(req, res, next);  
        };  
    }  
}
复制代码

Nest还实现了Guards,与其余提供程序同样,使用@Injectable()装饰器进行装饰。 Guards 能够控制用户能够访问的内容端点。 将在后续“身份验证”章节中更详细地讨论 Guards。

4.ORM

ORM是服务器和数据库之间通讯时最重要的概念之一:对象关系映射。 ORM提供内存中对象(诸如定义的 User 或 Comment 类) 和数据库中的关系表之间的映射。 容许您建立一个数据传输对象,该对象知道如何将存储在内存中的对象写入数据库,并将结果从SQL或其余查询语言读回内存。在这,咱们将讨论三种不一样的ORM: 两种关系型 orm 和一种针对 NoSQL 数据库的 orm。

TypeORM是Node.js中最成熟和最流行的ORM之一, Nest为其提供本身的包: @nestjs/typeorm,TypeORM很是强大,而且支持许多数据库,如MySQL,PostgreSQL,MariaDB,SQLite,MS SQL Server,Oracle和WebSQL。同时,Sequelize也是关系数据库的另外一个ORM。

若是TypeORM是最流行的ORM之一,那么Sequelize则是Node.js世界中最受欢迎的ORM之一。 它是用纯JavaScript编写的, 可是经过 sequelize-typescript 和 @types/sequelize 包进行了 TypeScript 绑定。Sequelize拥有强大的事务支持,关系,读取复制和更多功能。

最后一个ORM是处理非关系数据库或NoSQL数据库的ORM。mongoose 包处理MongoDB和JavaScript之间的对象关系。 与关系数据库相比,二者之间的实际映射关系要密切得多,由于MongoDB以JSON格式存储其数据,JSON格式表明JavaScript Object Notation。 Mongoose也有 @nestjs/mongoose ,并提供经过查询链查询数据库的能力。

5.REST API

REST是建立API的主要设计范例之一。它表明表明状态转移传输,并使用JSON做为传输格式,这与Nest存储对象的方式一致,所以它适合使用和返回 HTTP 调用。

客户端对服务器进行HTTP请求,服务器将根据URL和HTTP动词将调用路由到正确的Controller,可选择在到达Controller以前将其传递给一个或多个中间件。 而后,Controller将其交给service进行处理,其中可能包括经过ORM与数据库进行通讯。

若是客户端请求资源(GET请求),则返回一个可选主体; 若是是 POST/PUT/DELETE,则返回一个200 / 201 HTTP OK,若是没有响应主体。

6.WebSockets

Websocket 是从服务器链接和发送 / 接收数据的另外一种方式。

使用 websocket,客户端链接到服务器,而后订阅特定的通道。 而后,客户端能够将数据推送到订阅的通道。 服务器将接收此数据,而后将其广播到订阅该特定通道的每一个客户端。 这使得多个客户端均可以接收实时更新,而无需手动进行 API 调用。 大多数聊天应用程序使用WebSockets进行实时通讯,一旦其中一个成员发送消息,组消息中的每一个人都将收到消息。 与传统的请求-响应 API 相比,Websockets 容许更多的流式数据传输方法,由于 Websockets 能够在接收到数据时广播数据。

7.微服务

微服务容许将Nest将应用程序结构化为松散耦合服务的集合。 在Nest中,微服务略有不一样,由于它们是一个使用不一样于 HTTP 的传输层的应用程序。该层能够是TCP或Redis pub / sub等。

Nest支持TCP和Redis,但若是您与另外一个传输层结合,则可使用 CustomTransportStrategy 接口实现它。 微服务很棒,由于它们容许团队在全局项目中处理本身的服务,而且在不影响项目其他部分的状况下对服务进行更改,由于它是松散耦合的。 这使得持续交付和持续集成独立于其余团队的微服务。

8.GraphQL

正如咱们在上面看到的,REST 是设计 api 时的一种范例, 可是有一种新的方式来考虑建立和使用 api:GraphQL。

使用GraphQL,URL将接受带有JSON对象的查询参数,而不是每一个资源都有本身的URL指向。 此JSON对象定义要返回的数据的类型和格式。 Nest经过 @nestjs/graphql 包提供了这方面的功能。

这将包括项目中GraphQLModule, 它是Apollo服务器的包装器。

9.路由

在讨论Web框架时,路由是核心之一。当客户端须要访问服务器的端点时, 这些端点中的每个都描述了如何检索/建立/操做存储在服务器上的数据。 描述API端点的每一个Component必须具备@Controller() 装饰器,用于描述该组件的端点集的 API 前缀。

@Controller('hello')
export class HelloWorldController {
  @Get(‘world’)
  printHelloWorld() {
    return ‘Hello World’;
  }
}
复制代码

10.Nestg工具装饰器

@Module:项目中此可重用代码包的定义,它接受如下参数来定义其行为。
  ⋅⋅Imports:包含此模块中使用的组件。
  ⋅⋅Exports:导出模块。
  ⋅⋅Components:经过 Nest 注入的组件在这个模块上共享。
  ⋅⋅Controllers:在此模块中建立的控制器,这些控制器将根据定义的路由定义API端点。
复制代码
@Injectable:Nest中几乎全部东西都是能够经过构造函数注入的提供者。提供者用@Injectable()装饰。
  ..Middleware:在将请求传递给路由处理程序以前运行的函数。
  ..Interceptor:相似于中间件,它们在执行方法以前和以后绑定额外的逻辑,它们能够转换或彻底覆盖函数。拦截器的灵感来自面向方面编程(AOP)。
  ..Pipe:与拦截器功能的一部分相似,管道将输入数据转换为所需的输出。
  ..Guard:一个更聪明,更小众的中间件,Guards的惟一目的是肯定路由器处理程序是否应该处理请求。
  ..* Catch:告诉ExceptionFilter要查找的异常,而后将数据绑定到它。
复制代码
@Catch:将元数据绑定到异常过滤器,并告诉Nest过滤器只查找@Catch中列出的异常。
复制代码

11.OpenAPI (Swagger)

在编写 Nest 服务器时,api文档是很是重要的,不然使用该 API 开发客户端的开发人员不知道发送什么或将获得什么。

最流行的文档引擎之一是 Swagger。 像其余模块同样,Nest 为 OpenAPI (Swagger) spec,提供了一个专用模块 @nestjs/swagger。

这个模块提供了装饰器来帮助描述 API 的输入 / 输出和端点。 而后能够经过服务器上的一个端点访问该文档。

12.命令查询责任分离(CQRS)

命令查询责任分离(Command Query Responsibility Segregation,CQRS)的思想是,每一个方法要么是执行操做(Command)的方法,要么是执行请求数据(Query)的方法。

在咱们的示例应用程序的上下文中,不会在控制器中直接为一个端点建立数据库访问代码,而是建立一个组件(数据库服务) ,该组件具备getAllUsers()这样的方法,它将返回控制器服务能够调用的全部用户,从而将问题和答案分离到不一样的组件中。

13.测试

测试你的 Nest 服务器将是必要的,确保部署时没有不可预见的安全性问题。

有两种不一样类型的测试: 单元测试和 E2E 测试(端到端测试)。 单元测试是测试小代码片断或代码块,它能够像测试单个函数或 Controller、 Interceptor 或任何其余Injectable测试同样精细。

如今有不少流行的单元测试框架,Jasmine 和 Jest 是两个流行的框架。 Nest 提供了特殊的包,@nestjs/testing,用于在 *.spec.ts 及 *.test.ts 类中编写单元测试。

E2E 测试是另外一种经常使用的测试形式,它不一样于单元测试,它测试整个功能,而不是测试单个功能或组件,而这正是端到端测试这个名称的来源。

当应用程序变得很是庞大,以致于很难绝对地测试每一段代码和端点。 在这种状况下,您可使用 E2E 测试从头至尾测试应用程序,以确保一切顺利进行。

对于 E2E 测试,Nest 应用程序能够再次使用 Jest 库来模拟组件。 除了 Jest 以外,还可使用 supertest 库来模拟 HTTP 请求。

相关文章
相关标签/搜索