前言
首先,Nest 是什么?
根据官网介绍,Nest 是一个构建高效的、可伸缩的 Node.js 服务端应用的框架。Nest 支持 TS,结合了OOP、FP 和 FRP,可以使用 Express 或 Fastify 框架。
Nest (NestJS) is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with and fully supports TypeScript (yet still enables developers to code in pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).
Under the hood, Nest makes use of robust HTTP Server frameworks like Express (the default) and optionally can be configured to use Fastify as well!
此外,Nest 的哲学是提供开箱即用的应用架构,能用于创建高度可检验的、可伸缩的、低耦合的、易维护的应用。
Nest provides an out-of-the-box application architecture which allows developers and teams to create highly testable, scalable, loosely coupled, and easily maintainable applications.
简而言之,Nest 类似于 Koa、Express、Egg.js 等框架,但功能更加强大、代码编写更加高效,也是用于搭建服务端的一个框架。
初始化项目
官网指明了 Node.js (version >= 16),这里我们使用 nvm 进行切换。
全局安装 @nestjs/cli,并新建项目 nestjs-demo-240127。
nvm use 20.10.0
npm i -g @nestjs/cli
nest new nestjs-demo-240127
cd nestjs-demo-240127
pnpm start
pnpm start 启动项目,接着访问 http://localhost:3000 就可以看到 Hello World! 了。
Nest 的目录结构
src
app.controller.spec.ts
app.controller.ts
app.module.ts
app.service.ts
main.ts
test
app.e2e-spec.ts // e2e测试
jest-e2e.json // jest测试
.eslintrc.js
.prettierrc
.gitignore
nest-cli.json // 整个项目的配置文件
package.json
README.md
tsconfig.build.json // TypeScript语法构建时的配置文件
tsconfig.json // TypeScript的配置文件
其中,核心代码是 src 目录:
| filename | Role |
|---|---|
app.controller.ts | A basic controller with a single route. |
app.controller.spec.ts | The unit tests for the controller. |
app.module.ts | The root module of the application. |
app.service.ts | A basic service with a single method. |
main.ts | The entry file of the application which uses the core function NestFactory to create a Nest application instance. |
Nest 的约束
main.ts
首先看下代码入口main.ts文件。在当前文件中,我们引入了主模块 app.module ,作为 NestFactory.create 的传参,创建了一个app,该app指定了监听3000端口。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
xxx.module.ts 文件
xxx.module.ts 文件中定义了一个模块,该模块是用 @module() 装饰器定义的一个类。模块用于组织一个应用的结构,可以包含控制器、服务和其他模块。
在项目的主模块 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 {}
我们可以定义很多个模块,分别实现不同的路由功能。当我们定义了其他模块后,需要将各个模块引入主模块的 imports 数组中,这样才会生效。
// app.module.ts
@Module({
imports: [UserModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
xxx.controller.ts 文件
xxx.controller.ts 文件中定义了一个控制器。控制器负责处理 HTTP 请求并返回对应的响应。
在 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();
}
}
此外,我们可以添加一个新的路由,比如 /app:
@Get('/app')
sayHello(@Param('id') id: string): string {
return `Hello app.`;
}
@Controller() 默认是不传参的。我们也可以指定一个路径前缀,例如传参 /users。这意味着在当前文件中定义的所有路由都是以 '/users' 为前缀。
// user.controller.ts
@Controller('/users')
export class UsersController {
// ...
};
在控制器中,可以使用 @Get、@Post、@Put 等装饰器来声明路由处理函数。
xxx.service.ts 文件
xxx.server.ts 文件中定义了服务。在 Nest 中,服务用于封装与业务逻辑相关的代码。我们可以使用 @Injectable 装饰器来声明服务,并使用 @Inject 装饰器来注入其他服务或依赖。
举个例子,在 app.service.ts 文件中,代码如下:
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
在这里,AppService 服务是使用 @Injectable 装饰器声明的,其中定义的 getHello 函数会返回字符串 'Hello World!'。
后记
到此,一个简单的 Nest 项目的基本结构就介绍完了。
总的来说,一个 Nest 项目中,最主要的结构是module - controller - service。此外,Nest 中到处都是装饰器的身影,连指定 REST 风格的接口也是用了 @Get, @Post 等装饰器。