NestJS 实践记录(一):项目创建

最近想写一些功能接口给自己用,平常写前端比较多,我自己可怜的小服务器用 java 资源不是很充足,所以准备还是用 Node.js 来实现后端,选用 NestJS 作为本次开发的后端框架。

Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用 JavaScript 的渐进增强的能力,使用并完全支持 TypeScript (仍然允许开发者使用纯 JavaScript 进行开发),并结合了 OOP (面向对象编程)、FP (函数式编程)和 FRP (函数响应式编程)。

在底层,Nest 构建在强大的 HTTP 服务器框架上,例如 Express (默认),并且还可以通过配置从而使用 Fastify !

Nest 在这些常见的 Node.js 框架 (Express/Fastify) 之上提高了一个抽象级别,但仍然向开发者直接暴露了底层框架的 API。这使得开发者可以自由地使用适用于底层平台的无数的第三方模块。

NestJS 是我最近才了解到的一个非常流行的 Node.js 框架,用起来很有一种在编写 Spring Boot 的熟悉感,又能使用我更加熟悉的 JavaScript 来进行编写,是对我来说比较理想的后端框架。在此记录下实践的过程。

项目创建

本机环境:

  • Node.js: 14.17.0
  • npm: 7.11.2
  • NestJS: 8.0.0
  • TypeScirpt: 4.3.5

在安装好 Node.js 后,在全局安装 NestJS cli

1
npm install -g @nestjs/cli

运行如下命令创建项目,nest-cli会根据参数初始化项目文件。接着会让你选择想用的包管理器,npmyarn,我选择了yarn,因为我感觉国内即使换了源,yarn 似乎也更快一些。

1
nest new project-name

完成安装后就会显示如下信息。

目录结构可以参考 Nest framework TypeScript starter repository,项目就是基于这个创建的。我们可以看到这个模板使用了 TypeScript 语言,NestJS 也是可以基于 JavaScript 运行的,创建时加上参数配置如下所示即可。

1
nest new project-name -l JavaScript

更多参数可以参考 cli 的帮助,nest new --help

运行yarn start后,NestJS 就会开始运行,当显示Nest application successfully started时,即表示启动完成。

此时可以访问 http://localhost:3000,就能看到默认返回的 Hello World! 了。

项目结构

初始项目结构如下,我们主要关注 src 目录

初始内容由一个入口文件 main.ts、用于定义路由的 controller 文件app.controller.ts、用于具体方法实现的 provider 文件 app.service.ts、以及一个将 controller 和 service 文件关联在一起的 module 文件组成。

打开入口文件src/main.ts,内容如下。

1
2
3
4
5
6
7
8
9
// main.ts
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";

async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();

可以看到使用 Nest 工厂函数创建了 AppModule,然后将应用监听到了 3000 端口,现在应用将在 3000 端口接受 HTTP 请求。

1
2
3
4
5
6
7
8
9
10
11
// app.module.ts
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";

@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

在根模组 AppModule 中,注册了 AppController 和 AppService。值得注意的是,provider 需要在 module 中注册后才能为其他 provider 或者 controller 提供服务。

在 AppController 中,添加了默认的 Get 路由 getHello,通过引入的 provider AppService 来实际提供逻辑代码。因为没有指定路由的路径,那就是默认的根路径,也就是我们访问的http://localhost:3000/

1
2
3
4
5
6
7
8
9
10
11
12
13
// app.controller.ts
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();
}
}

在 provider AppService 中,我们可以看到这个getHello方法就是返回了一个Hello World!,也是就我们之前访问http://localhost:3000/看到的内容。

1
2
3
4
5
6
7
8
9
// app.service.ts
import { Injectable } from "@nestjs/common";

@Injectable()
export class AppService {
getHello(): string {
return "Hello World!";
}
}

到这里基本可以了解了 NestJS 的设计理念,主要就是由ControllerProviderModule组成成模组来提供服务。

  • Controller: 控制器,提供 Api 接口,定义路由等,不实际处理业务。
  • Provider: 也就是Service,为Controller或其他Provider提供服务,在这里编写实际的处理代码。
  • Module: 负责连接ProviderController,类似于命名空间的概念,在同一个Module中注册过的 Provider才能引入并提供服务。