从 0 拿捏 Nest.js✨:打工人的企业级 Node.js 框架通关指南
如果你是一名常年和 Node.js 打交道的打工人,曾经被 Express/Koa 的 "自由散漫" 折磨到秃头 ------ 团队代码风格五花八门,业务逻辑揉在路由里,维护起来堪比拆盲盒😵。那么你现在遇上了 Nest.js,可以彻底告别 "野路子",用规范的架构拿捏企业级后端开发。今天就带大家从 0 到 1 吃透 Nest.js,结合实战代码拆解核心知识点,包教包会!
一、Nest.js 核心简介
1. 什么是 Nest.js?
Nest.js(简称 Nest)是一款基于 Node.js 的企业级后端框架,主打 TypeScript 优先,借鉴了 Angular 的模块化、依赖注入等设计思想,把前端的工程化思维完美移植到后端。简单说,它就像给 Node.js 套上了 "西装"👔,让原本随性的后端开发变得规规矩矩、可维护性拉满。
2. 为什么需要 Nest.js?
Express 固然灵活,但 "灵活" 的另一面就是 "无约束":
- 多人协作时,有人把业务逻辑写在路由里,有人写在工具函数里,代码乱成一锅粥;
- 没有统一的架构规范,项目越大,越难维护;
- 缺乏内置的依赖注入、AOP(面向切面编程)等高级特性,实现复杂功能需要自己造轮子。
而 Nest.js 的出现就是为了解决这些痛点 ------ 它给 Node.js 后端开发制定了 "标准答案",让团队开发有章可循,还能无缝集成 TypeScript、ORM、微服务等生态,直接对标 Java 的 Spring 框架🌐。
3. Nest.js 核心优势(价值)是什么?
- TypeScript 原生支持:类型提示拉满,告别 "运行时才发现参数错了" 的坑;
- 模块化架构:把代码拆分成独立模块,低耦合、高内聚;
- 依赖注入:无需手动 new 实例,框架自动管理对象生命周期,解耦神器;
- 生态丰富:无缝集成 TypeORM/Sequelize(数据库)、Passport(认证)、Socket.io(实时通信)等;
- 企业级适配:支持微服务、网关、拦截器 / 过滤器等高级特性,满足大型项目需求。
二、Nest 项目初始化与目录结构
话不多说,咱们直接上手实操!用 VSCode 演示,一步到位搭建 Nest 项目👇
1. 环境准备
先确保电脑里装了这些 "基础装备":
- Node.js (>= 18.x,推荐 LTS 版本,毕竟稳定才是王道🤨);
- npm/pnpm (包管理器,选一个你顺手的就行)。
2. 安装 Nest CLI(核心工具)
Nest CLI 是快速创建项目、生成模块 / 控制器 / 服务的 "神兵利器",全局安装即可:
bash
# npm 安装
npm install -g @nestjs/cli
3. 创建并启动 Nest 项目
bash
# 创建新项目(my-nest-app 是项目名,可自定义)
nest new my-nest-app
# 进入项目目录
cd my-nest-app
# 启动开发服务(热更新,改代码不用手动重启,爽!)
npm run start:dev
启动成功后,访问 http://localhost:3000,看到熟悉的 "Hello World!",说明项目初始化搞定啦🎉!
4. 标准的 Nest 项目目录结构
初始化后的目录是 Nest 官方钦定的 "标准答案",企业级项目都按这个来,千万别乱改核心目录名!核心结构(结合实战代码)如下:
plaintext
src/
├── app.controller.ts # 根控制器(处理根路径请求)
├── app.module.ts # 根模块(项目的"总入口")
├── app.service.ts # 根服务(处理根路径业务逻辑)
├── main.ts # 应用启动入口(唯一!)
├── database/ # 数据库模块(自定义,封装数据库操作)
│ ├── database.controller.ts
│ ├── database.module.ts
│ ├── database.service.ts
└── todos/ # 待办事项模块(自定义,业务模块示例)
├── todos.controller.ts
├── todos.module.ts
├── todos.service.ts

5. 入口文件:main.ts(唯一启动入口)
src/main.ts 是 Nest 应用的 "发动机"🚀,负责创建应用实例、启动服务,核心代码几乎不用改,咱们结合实战代码拆解:
typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
// 加载.env环境变量文件
import { config } from 'dotenv';
config();
async function bootstrap() {
// 创建Nest应用实例,关联根模块AppModule
const app = await NestFactory.create(AppModule);
// 配置端口:优先用环境变量PORT,没有就用3000(ES2020的空值合并运算符??,超好用!)
await app.listen(process.env.PORT ?? 3000);
}
// 启动应用
bootstrap();
注释中提到配置端口,我们来讲解一下:
(1)为什么要手动配置端口?
- 避免端口冲突:默认情况下,Node.js 或 NestJS 会使用 3000 端口启动服务;如果你在本地同时运行多个项目(比如:前端、后端、数据库、其他服务),它们都用 3000 端口就会冲突;手动配置端口可以让你为每个服务分配唯一的端口号,避免冲突。
- 便于团队协作与环境隔离:不同开发者可能使用不同的端口习惯;使用 .env 配置端口可以让每个人根据自己的环境设置,互不干扰。
- 支持多环境部署(开发 / 测试 / 生产):开发时用 3000,测试用 4000,生产用 80(HTTP)或 443(HTTPS);通过 .env文件管理不同环境的配置,无需修改代码。
(2)配置步骤
- 根目录新建
.env文件,添加端口配置:PORT=1234; - 安装 dotenv:
npm i dotenv; - 在 main.ts 中导入并执行
config(),加载.env 文件; - 用
process.env.PORT读取端口,配合??设置默认值。

重新执行 npm run start:dev 启动成功后,访问 http://localhost:5678,看到熟悉的 "Hello World!",说明手动配置端口成功了🎉!
(3)手动配置端口注意事项
- 不要使用前导零(避免八进制解析);始终使用纯十进制数字,不加前导零。
- 避免使用知名/系统保留端口,如:特权端口(需 root 权限),如 80(HTTP)、443(HTTPS)、22(SSH)。
- 启动服务前检查是否已有进程占用该端口,确保端口未被占用。
三、Nest 三大核心支柱
Nest 的所有代码组织都围绕Module(模块)、Controller(控制器)、Provider(提供者) 展开,这是 Nest 的 "骨架"🦴,必须吃透!
下面将结合todos 待办列表来对三大核心支柱进行拆分讲解:
1. 模块 (Module) - 应用的「组织单元」,一切的容器
(1)代码(todos.module.ts)
typescript
import { Module } from '@nestjs/common';
import { TodoController } from './todos.controller'; // 关联该模块的控制器
import { TodosService } from './todos.service'; // 关联该模块的服务(提供者)
@Module({
// 声明该模块下的控制器
controllers: [TodoController],
// 声明该模块下的提供者(服务、工厂等)
providers: [TodosService],
})
export class TodoModule {}
(2)Module 核心作用
如果把 Nest 应用比作一家公司🏢,Module 就是 "部门":
- 每个业务模块(比如待办事项、用户、订单)对应一个 Module;
- 根模块 AppModule 是 "总经办",负责整合所有子模块(比如 TodoModule、DatabaseModule);
- 模块内部声明自己的控制器和提供者,还能通过
exports导出提供者,供其他模块使用; - 全局模块(比如 下面集成数据库讲解中的
DatabaseModule加了 @Global ())相当于 "行政部",所有模块都能直接用,不用手动导入。
app.module.ts 通过 imports 导入 todos.module.ts,从而将用户功能集成到整个应用中。

(3)核心装饰器:@Module ()
- 装饰器是什么? 装饰器(Decorator)在 TypeScript / JavaScript(尤其是 NestJS 等现代框架)中是一种声明式、元编程的语法特性,它的核心作用是:
在不修改类或方法原有代码的前提下,动态地为它们添加元数据、行为或功能。
- @Module () 的作用:标记一个类为 Nest 模块,接收一个配置对象,声明模块的控制器、提供者、导入的模块、导出的提供者。
2. 控制器 (Controller) - 应用的「门面」,处理请求
控制器是应用的 "前台小姐姐"💁♀️,负责接收客户端的请求(GET/POST/DELETE 等),把请求转发给服务处理,最后返回响应。
(1)代码(todos.controller.ts)
typescript
import { Controller, Get, Post, Body, Delete, Param } from '@nestjs/common';
import { TodosService } from './todos.service';
import { ParseIntPipe } from '@nestjs/common'; // 路由参数转整数的管道
// 标记为控制器,指定路由前缀:所有该控制器的接口都以/todos开头
@Controller('todos')
export class TodoController {
// 依赖注入:自动创建TodosService实例,不用手动new!
constructor(private readonly todosService: TodosService) {}
// GET请求:/todos,获取所有待办事项
@Get()
getTodos() {
// 只转发请求,业务逻辑全交给服务处理
return this.todosService.findAll();
}
// POST请求:/todos,添加待办事项
@Post()
// @Body('title'):从请求体中提取title字段
addTodo(@Body('title') title: string) {
return this.todosService.addTodo(title);
}
// DELETE请求:/todos/:id,删除指定id的待办事项
@Delete(':id')
// @Param('id', ParseIntPipe):提取路由参数id,并转为整数
deleteTodo(@Param('id', ParseIntPipe) id: number) {
return this.todosService.deleteTodo(id);
}
}
(2)Controller 核心作用
- 映射 HTTP 请求方法(GET/POST/DELETE 等)和路由;
- 提取请求参数(路径参数、请求体、查询参数等);
- 转发请求到对应的服务处理业务逻辑;
- 返回响应给客户端。
(3)核心装饰器:@Controller ()
标记类为控制器,可指定路由前缀(比如@Controller('todos'),所有接口都以 /todos 开头),简化路由编写。
(4)核心原则
划重点❗️控制器只做 "请求转发和响应",绝对不能写业务逻辑!所有业务逻辑都交给 Provider(Service)处理,这是 Nest 的强制最佳实践,也是解耦的核心 ------ 比如前端改了请求参数格式,只需要改控制器的参数提取逻辑,服务层完全不用动。
(5)控制器常用装饰器(高频)
@Get()/@Post()/@Delete():映射对应的 HTTP 请求方法;@Param():提取路由参数(比如 /:id);@Body():提取请求体数据;@Query():提取查询参数(比如?t=123);@Header():设置响应头。
3. 提供者 (Provider) - 应用的「核心」,处理业务逻辑
提供者是应用的 "后端打工人"👷♂️,所有业务逻辑(查数据、处理逻辑、调用第三方接口等)都在这里实现。
(1)代码(todos.service.ts)
typescript
import { Injectable } from '@nestjs/common';
// 定义Todo接口,约束数据类型(TypeScript yyds!)
export interface Todo {
id: number;
title: string;
completed: boolean;
}
// 标记为提供者,Nest会自动管理其生命周期
@Injectable()
export class TodosService {
// 模拟数据库:内存中的待办事项列表
private todos: Todo[] = [
{
id: 1,
title: '疯狂星期四~',
completed: false,
},
{
id: 2,
title: '学习好痛苦~',
completed: true,
},
];
// 业务逻辑:获取所有待办事项
findAll(): Todo[] {
return this.todos;
}
// 业务逻辑:添加待办事项
addTodo(title: string) {
const todo: Todo = {
id: +Date.now(), // 用时间戳生成唯一id
title,
completed: false,
};
this.todos.push(todo);
return todo;
}
// 业务逻辑:删除待办事项
deleteTodo(id: number) {
// 调用数组的 `filter()` 方法,创建一个新数组,只保留满足条件的元素。
// 条件是:`todo.id !== id`
this.todos = this.todos.filter((todo) => todo.id !== id);
return {
message: 'Todo deleted',
code: 200,
};
}
}
(2)Provider 核心作用
处理所有业务逻辑:数据处理、数据库操作、第三方接口调用、业务规则校验等,是应用的 "核心大脑"。
(3)核心特点
提供者是可注入的 !这是 Nest 最核心的特性之一 ------ 我们不需要手动new TodosService(),只需要在控制器的构造函数中声明依赖,Nest 会自动创建实例并注入,还能管理实例的生命周期(比如单例模式)。
(4)提供者的本质
很多人以为 Provider 就是 Service,其实 Service 只是 Provider 的 "最常见形态"🤔!在 Nest 中,任何被@Injectable()标记的类、值、工厂函数、异步工厂都能作为 Provider,比如数据库连接池(PG_CONNECTION)也是一种 Provider(在下文数据库配置中也会详细讲解):
typescript
// database.module.ts中的数据库连接池提供者
{
provide: 'PG_CONNECTION', // 唯一标识
useFactory: (): Pool => { // 工厂函数创建实例
return new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
// ...其他配置
});
},
}
(5)效果展示(我们将使用Apifox工具模拟请求)
启动项目后,访问http://localhost:5678/todos,能看到待办事项列表;POST 请求/todos(body 传 title)能添加新待办;DELETE 请求/todos/1能删除 id 为 1 的待办,完美跑通✅!

四、Nest 核心特性:依赖注入 (DI)
1. 什么是依赖注入?
依赖注入(DI)是一种设计模式:简单说,就是 "谁需要某个对象,框架就把这个对象送上门"🚚,而不是让你自己去创建(new)。比如 TodoController 需要 TodosService,Nest 就自动把 TodosService 的实例注入到 TodoController 的构造函数中。
2. 为什么需要依赖注入?
- 解耦:控制器不用关心服务的创建逻辑,只需要用就行;
- 易测试:测试时可以轻松替换成模拟的服务(比如模拟 TodosService 返回固定数据);
- 复用性高:一个服务可以被多个控制器注入使用;
- 生命周期管理:Nest 统一管理对象的创建、销毁,避免内存泄漏。
3. 具体怎么实现?
咱们以 TodoController 注入 TodosService 为例,拆解代码逻辑:
typescript
// 1. 标记TodosService为可注入的提供者
@Injectable()
export class TodosService {}
// 2. 在TodoModule中声明TodosService为提供者
@Module({
providers: [TodosService],
})
export class TodoModule {}
// 3. 在TodoController中声明依赖,Nest自动注入
export class TodoController {
// private readonly todosService: TodosService:声明依赖
constructor(private readonly todosService: TodosService) {}
// 直接使用注入的实例
getTodos() {
return this.todosService.findAll();
}
}
核心逻辑:
- Nest 启动时,会扫描所有模块的提供者,建立 "依赖图谱";
- 当创建 TodoController 实例时,Nest 发现它依赖 TodosService,就会先创建 TodosService 实例(单例),再注入到 TodoController 中;
- 整个过程无需手动 new,框架全搞定!
五、数据库集成
Nest 对主流数据库 / ORM 都有官方封装,咱们以 PostgreSQL(pg)为例,演示如何集成数据库👇
1. 安装 pg 包
PostgreSQL 的 Node.js 驱动,先安装:
bash
npm install pg
2. 在.env 文件内配置数据库相关变量
env
# 数据库配置
DB_USER=postgres # 默认数据库用户名
DB_HOST=localhost # 数据库地址
DB_NAME=nest_demo # 你创建数据库名
DB_PASSWORD=123456 # 你的数据库密码
DB_PORT=5432 # 默认数据库端口

3. 编写 database 模块
(1)database.module.ts(数据库模块核心)
typescript
// 数据库基础服务
import { Module, Global } from '@nestjs/common';
import * as dotenv from 'dotenv';
dotenv.config(); // 加载环境变量
// 数据库驱动,需要下载
import { Pool } from 'pg';
import { DatabaseService } from './database.service';
import { DatabaseController } from './database.controller';
@Global() // 标记为全局模块,所有模块都能直接使用,无需手动导入
@Module({
// 声明数据库控制器
controllers: [DatabaseController],
providers: [
// 提供者1:数据库连接池(PG_CONNECTION为唯一标识)
{
provide: 'PG_CONNECTION',
// useFactory:工厂函数,创建连接池实例
useFactory: (): Pool => {
return new Pool({
user: process.env.DB_USER, // 从环境变量读用户名
host: process.env.DB_HOST, // 数据库地址
database: process.env.DB_NAME, // 数据库名
password: process.env.DB_PASSWORD, // 密码
port: parseInt(process.env.DB_PORT || '5432', 10), // 第二个参数 `10` 表示使用 十进制(base-10) 解析。
});
},
},
// 提供者2:数据库服务
DatabaseService,
],
// 导出连接池和服务,供其他模块使用
exports: ['PG_CONNECTION', DatabaseService],
})
export class DatabaseModule {}
(2)database.service.ts(数据库业务逻辑)
typescript
import { Injectable, Inject } from '@nestjs/common';
import { Pool } from 'pg';
// 定义返回数据的类型
type NowRow = {
now: string;
};
@Injectable()
export class DatabaseService {
// 注入数据库连接池(通过唯一标识PG_CONNECTION)
constructor(
@Inject('PG_CONNECTION')
private readonly pool: Pool,
) {}
// 业务逻辑:查询SQL(这里示例查users表,实际可替换为任意SQL)
async findNow(): Promise<NowRow> {
// 执行SQL查询
const result = await this.pool.query<NowRow>('SELECT * from users');
// 注意:result.rows是数组,返回整个users表
return result.rows;
}
}
(3)database.controller.ts(数据库接口)
typescript
import { Controller, Get } from '@nestjs/common';
import { DatabaseService } from './database.service';
// 路由前缀:/database
@Controller('database')
export class DatabaseController {
// 注入数据库服务
constructor(private readonly databaseService: DatabaseService) {}
// GET请求:/database/now,获取数据库当前时间
@Get('now')
async getNow(): Promise<{ now: string }> {
const now = await this.databaseService.findNow();
return now;
}
}
4. 效果展示
在数据库xuebi中我们创建了users表,并插入了测试数据:

启动项目后,访问http://localhost:5678/database/now,能看到数据库返回的数据,说明数据库集成成功🎉!

5. 小小总结
Nest 集成数据库的核心思路:
- 把数据库连接池封装成 Provider,通过依赖注入供服务使用;
- 数据库操作的业务逻辑写在 DatabaseService 中;
- 控制器只负责暴露接口,转发请求到 DatabaseService;
- 全局模块让所有业务模块都能轻松使用数据库服务。
六、面试官会问
学完这些,面试时遇到 Nest.js 相关问题再也不慌😎,高频问题整理:
1. Nest 的三大核心支柱是什么?分别有什么作用?
Nest 的三大核心支柱是 Controllers(控制器) 、Providers(提供者) 、Modules(模块) ,三者共同构成了 Nest 应用的核心架构:
- Controllers(控制器) :核心作用是处理客户端请求 并返回响应,是应用的 "入口层"。负责定义路由规则、接收请求参数(Query/Param/Body 等)、调用对应的业务逻辑(Providers),并将处理结果返回给客户端。示例:代码中
TodoController定义了/todos路径的 GET/POST/DELETE 路由,接收请求后调用TodosService处理业务。 - Providers(提供者) :是 Nest 中实现业务逻辑的核心(如 Service、Repository 等),具备依赖注入 能力,是应用的 "业务逻辑层"。Providers 可以被注入到控制器、其他 Providers 中,实现代码解耦和复用。示例:
TodosService、DatabaseService都是典型的 Provider,封装了 Todo 增删查、数据库操作等核心逻辑,被控制器注入使用。 - Modules(模块) :是 Nest 应用的 "组织单元",负责封装和组合控制器、提供者 ,定义应用的模块边界。每个模块专注于一个业务域(如
TodoModule、DatabaseModule),通过imports/exports实现模块间的依赖共享。示例:AppModule导入TodoModule和DatabaseModule,整合整个应用的模块;TodoModule声明了自身的控制器和服务。
2. 什么是依赖注入?Nest 中如何实现依赖注入?
(1)依赖注入(DI)的定义
依赖注入是一种设计模式,核心思想是将类的依赖项(如 Service)由外部容器(而非类自身)创建并注入,实现类与依赖的解耦,便于测试和维护。例如:控制器不需要手动实例化 Service,而是由 Nest 容器自动注入。
(2)Nest 中实现依赖注入的方式
Nest 基于 TypeScript 的装饰器和元数据实现依赖注入,核心步骤:
- 步骤 1 :将依赖类标记为
@Injectable()(提供者),声明其可被注入;示例:TodosService上的@Injectable()装饰器,标记该类为可注入的 Provider。 - 步骤 2 :在模块的
providers数组中注册该 Provider,让 Nest 容器管理其生命周期;示例:TodoModule的providers: [TodosService]注册了 Todo 服务。 - 步骤 3 :在需要使用的类(如控制器)的构造函数中声明依赖,Nest 自动注入实例;示例:
TodoController构造函数中private readonly todosService: TodosService,Nest 会自动创建TodosService实例并注入。 - 扩展 :自定义注入(如数据库连接池):通过
provide定义令牌、useFactory创建实例,再通过@Inject('令牌')注入;示例:DatabaseModule中注册PG_CONNECTION连接池,DatabaseService通过@Inject('PG_CONNECTION')注入。
3. Controller 和 Service 的职责分离原则是什么?为什么要这么设计?
(1)职责分离原则
- Controller(控制器) :仅负责请求处理和响应返回,不包含业务逻辑。核心职责是:路由映射、参数校验 / 解析、调用 Service、返回响应。
- Service(服务,属于 Provider) :仅负责核心业务逻辑,不处理请求 / 响应。核心职责是:数据处理、数据库交互、业务规则实现,是纯逻辑层。
(2)设计原因
- 单一职责:符合 SOLID 原则,控制器专注请求层,服务专注逻辑层,代码更易理解和维护;
- 复用性:Service 可被多个 Controller 复用(如多个接口调用同一业务逻辑);
- 可测试性:Service 是纯逻辑层,无需依赖请求上下文,可单独编写单元测试;
- 解耦 :请求逻辑和业务逻辑分离,修改业务逻辑无需改动控制器,降低维护成本。示例:代码中
TodoController仅处理/todos的请求路由,而 Todo 的增删查逻辑全部在TodosService中实现,两者完全分离。
4. Nest 中的 Module 有什么作用?全局模块怎么实现?
(1)Module 的作用
Module 是 Nest 应用的模块化组织单元,核心作用:
- 封装性 :将相关的 Controller、Provider 组合成一个模块,划分业务域(如
TodoModule仅处理 Todo 相关逻辑); - 依赖管理 :通过
imports导入其他模块的 Provider,通过exports导出自身的 Provider 供其他模块使用; - 生命周期管理:Nest 容器基于模块管理 Provider 的实例化和销毁;
- 隔离性 :模块内的 Provider 默认仅在模块内可见,需显式
exports才能被外部使用。
(2)全局模块的实现
全局模块是指注册后可被所有模块使用,无需在每个模块的 imports 中显式导入,实现方式:
- 步骤 1:在模块类上添加
@Global()装饰器; - 步骤 2:在模块的
exports中声明需要全局共享的 Provider;示例:代码中DatabaseModule标记了@Global(),且exports: ['PG_CONNECTION', DatabaseService],因此整个应用的所有模块都可直接注入DatabaseService或PG_CONNECTION,无需重复导入DatabaseModule。
5. 如何在 Nest 中集成数据库?连接池的作用是什么?
(1)Nest 中集成数据库(以 PostgreSQL 为例,对应代码示例)
核心步骤:
- 步骤 1 :安装数据库驱动(如
pg)和环境变量管理包(dotenv); - 步骤 2 :创建数据库模块,配置连接池(通过
useFactory初始化连接池);示例:DatabaseModule中通过Pool创建 PostgreSQL 连接池,读取.env中的数据库配置(用户、主机、密码等); - 步骤 3 :创建数据库 Service,注入连接池并封装数据库操作;示例:
DatabaseService注入PG_CONNECTION连接池,实现findNow()方法执行 SQL 查询; - 步骤 4 :将数据库模块设为全局模块,供其他业务模块(如
TodoModule)注入使用。
(2)连接池的作用
连接池是数据库连接的 "管理容器",核心作用:
- 复用连接:避免频繁创建 / 销毁数据库连接(创建连接是高开销操作),提升性能;
- 控制并发:限制最大连接数,防止数据库因过多连接崩溃;
- 资源管理 :自动管理连接的分配、回收,简化开发(无需手动管理连接的打开 / 关闭);示例:代码中
Pool实例化时配置了连接参数,Nest 启动时创建连接池,后续所有数据库操作复用池中的连接。
6. Nest 的装饰器有什么作用?
Nest 基于 TypeScript 装饰器实现核心功能,装饰器的作用是为类、方法、参数添加元数据,Nest 容器解析这些元数据,实现路由注册、依赖注入、请求解析等核心能力。装饰器是 Nest 实现 "声明式编程" 的核心。
七、结语
Nest.js 看似上手有门槛,但只要吃透 "模块化、依赖注入、控制器 / 服务职责分离" 这几个核心思想,就能快速拿捏✅。它不是替代 Express/Koa,而是在其基础上做了一层优雅的封装,让 Node.js 后端开发从 "野路子" 走向 "企业级"。
从写第一个 Hello World,到集成数据库实现业务接口,你会发现 Nest 的规范和工程化思维能大幅提升开发效率,尤其是团队协作时,再也不用对着乱糟糟的代码头大。赶紧动手敲一遍代码,把知识点落地,你会发现 Nest 真的香到离谱😜!