NestJS 入门核心梳理:模块化架构、装饰器与依赖注入

前言

说起 Node.js 后端开发,很多人从 Express、Koa 这类轻量框架转向 NestJS 时,最不适应的就是满眼的 @ 装饰器、模块化拆分和依赖注入。

NestJS 是 Node 运行环境下的企业级后端开发框架,默认原生支持 TypeScript,全面贯彻模块化设计思想,非常适合构建中大型 Web 服务、系统集成服务乃至微服务架构。

本文就从基础定位、目录结构到核心组件,再到底层设计模式,把 NestJS 入门最核心的知识点一次性串清楚。


一、后端开发到底在做什么?

在聊框架之前,先明确后端开发的核心工作,大致分为三类:

  1. 提供 API 接口:最常见的 Web 开发场景,给前端、客户端提供 HTTP 接口,完成数据增删改查。
  2. 系统集成与底层服务:处理并发、对接第三方服务、封装底层能力、做任务调度等。
  3. 微服务架构:拆分业务域,构建分布式微服务集群,支撑复杂业务系统。

NestJS 的设计目标,就是用标准化的模块化架构,优雅地支撑以上所有场景。


二、快速安装与项目初始化

NestJS 提供了官方 CLI 工具,用来快速创建项目、生成模块 / 控制器等代码片段。

1. 全局安装 CLI

css 复制代码
npm i -g @nestjs/cli

-g 代表全局安装,安装完成后,在电脑任意目录都可以使用 nest 命令,只需要安装一次。

2. 创建项目

在你想存放代码的目录下执行:

arduino 复制代码
nest new hello-nest

执行过程中会提示选择包管理器、是否开启可观测性、选择模块系统,入门阶段建议选择:

  • 包管理器:npm /pnpm 均可
  • 可观测性:No(初学不需要监控链路)
  • 模块系统:ESM(ES Modules,现代标准)

三、核心设计:高度模块化的架构思想

NestJS 最核心的特征就是模块化。整个应用由一个个模块拼接而成,每个模块职责单一,各自管理自己的控制器、服务和依赖。

基础目录结构

ruby 复制代码
src
├── main.ts          # 项目入口,启动应用
├── app.module.ts    # 根模块,整个应用的入口模块
├── app.controller.ts # 根控制器
└── app.service.ts   # 根服务

模块化层级

markdown 复制代码
整个应用 App
    └── 根模块 AppModule
            ├── 导入其他子模块
            ├── 注册控制器 Controller
            └── 注册服务 Provider / Service

每个模块都是一个独立的单元,通过 @Module 装饰器声明自己的依赖和组件,模块之间可以互相导入、复用。


四、核心三件套:Module / Controller / Service

NestJS 代码里最常见的三个装饰器,分别对应三层职责,分层清晰是企业级框架的典型特征。

1. @Module:模块组装器

@Module() 打在类上,标记这个类是一个 Nest 模块,作用是组装和注册:告诉框架这个模块包含哪些控制器、哪些服务,以及需要导入哪些其他模块。

typescript 复制代码
import { Module } from '@nestjs/common';
import { AppController } from './app.controller.js';
import { AppService } from './app.service.js';

@Module({
  imports: [],          // 导入其他依赖模块
  controllers: [AppController], // 注册当前模块的控制器
  providers: [AppService],     // 注册当前模块的服务(提供者)
})
export class AppModule {}
  • imports:引入其他模块,比如用户模块、数据库模块
  • controllers:注册控制器,只有写在这里的控制器,它的路由才会生效
  • providers:注册服务,注册后 Nest 的依赖注入才能自动创建实例

2. @Controller:请求接收器

@Controller() 标记一个类为控制器,它是 HTTP 请求的入口,负责接收请求、校验参数、调用业务层、返回响应结果。

简单说:控制器负责 "接请求、调服务、返结果",不写复杂业务逻辑。

typescript 复制代码
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service.js';

@Controller()
export class AppController {
  // 构造函数注入服务
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    console.log('/的控制器');
    // 业务逻辑全部交给 service 层
    return this.appService.getHello();
  }
}
  • @Controller() 可以传入路由前缀,比如 @Controller('user'),该控制器下所有接口都会加上 /user 前缀
  • @Get() 标记方法处理 GET 请求,同理还有 @Post()@Put()@Delete()

3. @Service:业务逻辑层

Service 是真正写业务逻辑的地方:数据计算、数据库操作、第三方调用都写在这里。

控制器层尽量保持轻薄,业务逻辑下沉到 Service,好处是逻辑可复用、易测试、职责清晰。


五、底层原理:语法糖与设计模式

看懂了用法,再深入一层:NestJS 这些简洁的写法背后,是 TypeScript 语法特性和经典设计模式的支撑。

1. TS 构造函数参数修饰符

很多人刚接触会疑惑:为什么构造函数里写 private readonly appService,就能用 this.appService 访问?

这是 TypeScript 的专属语法糖:当构造函数参数加上 private / public / protected 修饰符时,TS 编译器会自动完成两件事

  1. 自动给类声明一个同名的实例属性
  2. 构造函数内部自动执行 this.xxx = xxx 赋值
typescript 复制代码
// 语法糖写法
constructor(private readonly appService: AppService) {}

等价于完整写法:

typescript 复制代码
private readonly appService: AppService;
constructor(appService: AppService) {
  this.appService = appService;
}

注意:如果不加修饰符,它就只是构造函数的局部参数,出了构造函数就无法通过 this 访问。

2. 装饰器模式

代码里到处都是的 @Module@Controller@Get,并不是注释,也不只是为了好看,它们是装饰器语法,底层思想来自经典的「装饰器设计模式」。

装饰器模式的核心:不修改原有类的代码,动态给对象扩展额外功能,包装原有对象,在前后增加逻辑

NestJS 中的装饰器本质是函数,它会给类、方法打上元数据标签。框架启动时扫描这些标签,自动完成路由注册、模块组装、依赖注入。

简单理解:装饰器就是给类 / 方法贴电子标签,框架能读懂标签并按标签工作。删掉装饰器,对应的功能就会直接失效。

3. 依赖注入(DI)

你不需要自己 new AppService(),只要在构造函数里声明类型,Nest 就会自动把实例注入进来。

这就是依赖注入:对象的创建和销毁由框架统一管理,开发者只需要声明依赖,不需要手动实例化。 好处是解耦、便于测试、便于统一管理实例生命周期。


六、总结

最后用一句话把 NestJS 入门核心串起来:

NestJS 以模块化为骨架,用 @Module 组装组件,用 @Controller 接收请求,用 @Service 处理业务,依托 TypeScript 语法糖和装饰器模式,实现了优雅的依赖注入,构建出高内聚、低耦合的企业级后端架构。

掌握这些核心概念,再去写接口、拆模块、接数据库,思路就会清晰很多。后续还可以继续深入中间件、拦截器、管道、数据库集成等进阶内容。

相关推荐
唐青枫26 分钟前
别只会 malloc:Zig Allocator、所有权与内存生命周期实战
后端
风曳丷1 小时前
12|用 Attack Tree 和 Trace 固化证据
后端
江华森1 小时前
云原生从0到1:Kubernetes 工作负载实战——Deployment/Service/滚动更新/弹性伸缩
前端·后端
江华森1 小时前
《云原生从0到1:4台华为云ECS搭建Kubernetes 1.28集群实录(上)——环境与踩坑全记录》
前端·后端
那咋乎吧1 小时前
数据包到达网卡后到用户态应用程序的全流程
后端
程序猿阿越1 小时前
kubelet源码阅读
后端·kubernetes·源码阅读
烂蜻蜓2 小时前
Flask入门教程(九):模板渲染——用Jinja2构建动态页面
后端·python·flask
QQ_21696290962 小时前
【源码编号:project93375】SpringBoot汽车维修管理信息系统:客户车辆、维修预约、工单派发、配件结算全流程实战
java·spring boot·后端·汽车·springboot·需求分析
gis开发之家3 小时前
Spring Boot 4 深度解析,JdbcTemplate 实战——轻量级数据库操作方案
java·数据库·spring boot·后端