CodeRoad Map 程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。
由 程序员柏风 独立维护 · 关于作者
学习 更多
NestJS 是什么
这一课你将能做到
用人话说清楚 NestJS 比原生 Express 多了什么:Module 分包、依赖注入容器、装饰器路由
对照本站 Spring Boot,说出 @Controller / @Injectable / Guard / Pipe 分别对应谁
给出「什么项目选 Nest、什么项目继续 Express、什么交给 Spring Boot」的判断依据
为什么要学
你要做一个刷题平台后端:题库管理、提交答案、自动判分、错题本、排行榜。用 Express 从 app.get("/questions") 起步很轻快,但功能一多问题就来了:30 个路由文件里各自 new XxxService()、业务规则散落在回调里、单元测试想替换掉数据库全靠手动重写。代码能不能维护,取决于作者当天的自觉。
NestJS 的解法是:在 Node.js + TypeScript 上套一层企业级骨架——强制按 Module 分包、用依赖注入容器装配 Service、用装饰器声明路由和横切逻辑。每个类放哪、谁能注入谁,框架都帮你管起来。
本站生产环境的主 API 仍是 Spring Boot。所以学 Nest 对本站读者有两个现实意义:一是全栈 TypeScript 团队或 BFF(Backend for Frontend,面向前端的聚合层)场景确实会用到;二是它和 Spring Boot 的分层几乎一一对应,学它等于换一种语言把 Controller-Service-Repository 这套架构思想再练一遍,理解会更深。
先建立图像
一次请求在 Nest 内部的流水线:
HTTP 请求
→ Middleware(中间件,Express 风格)
→ Guard(守卫:有没有权限进来?)
→ Interceptor(拦截器:方法前后织入,可改返回)
→ Pipe(管道:参数转换与校验)
→ Controller(控制器:HTTP 适配,不写业务)
→ Service(服务:业务规则与编排)
→ Repository / 外部 API(持久化与第三方调用)
Module 在旁边负责「装配清单」:这个包里有哪些 Controller、哪些 Service、哪些 Service 允许别人用;DI 容器按构造器声明的类型自动把实例塞进去。
Express 与 Nest 对比:
对比项 Express NestJS 项目结构 自由发挥 Module / Controller / Provider 强制分层 语言 可选 TypeScript 默认 TypeScript 优先 依赖获取 手写 require / new IoC 容器按构造器注入 横切逻辑 手写中间件 Guard / Interceptor / Pipe 分工 整体感觉 轻量 HTTP 胶水 Spring / Angular 风格的完整骨架
与 Spring Boot 速查表:
Spring Boot NestJS @RestController@Controller()@Service@Injectable()@Autowired构造器参数注入(也可用 @Inject) HandlerInterceptor / AOPNestInterceptor
Spring Security 过滤器链 CanActivate Guard
@Valid + Bean ValidationValidationPipe + class-validator
@ControllerAdvice全局 ExceptionFilter
application.yml + @ValueConfigModule + ConfigService
底层默认跑在 Express 之上(也可以切换到 Fastify)。你启动的还是 Node 进程,改变的是代码的组织方式,不是运行时。
跟着做
步骤 1:确认前置环境 NestJS 10 建议 Node.js 18 或 20 以上的 LTS 版本。版本过低先升级 Node。本课程默认你已经写过基础的 Express 和 TypeScript,能看懂接口、类与泛型。
步骤 2:浏览官方文档的 Introduction 打开 docs.nestjs.com ,阅读 Introduction 一节即可,重点留意三个词:TypeScript、modular(模块化)、dependency injection(依赖注入)。不用细读长代码,先混个脸熟。
步骤 3:读懂一个真实控制器长什么样 下面是刷题平台的题库控制器,后续课程会亲手把它跑起来,现在先逐行理解:
import { Controller, Get, Param } from "@nestjs/common";
import { QuestionsService } from "./questions.service";
// 人话:这个类负责处理 /questions 开头的请求
@Controller("questions")
export class QuestionsController {
// 人话:我需要一个 QuestionsService,别让我自己 new
constructor(private readonly questions: QuestionsService) {}
// 人话:GET /questions 时调用这个方法
@Get()
findAll() {
return this.questions.findAll();
}
// 人话:GET /questions/123 时,把 123 作为 id 传入
@Get(":id")
findOne(@Param("id") id: string) {
return this.questions.findOne(Number(id));
}
}
装饰器是写在类和方法上的「标签」,编译时以元数据形式保留;运行时 Nest 读取这些标签,自动注册路由、解析依赖。你几乎不再手写 app.get(...),而是「定义类、贴标签、写方法」。
步骤 4:写下三句选型结论
本站核心业务 API(题库、判分、支付等企业系统)→ 继续 Spring Boot。
全栈 TS 团队的中型 API,或给前端做 BFF 聚合层 → 选 NestJS。
一次性脚本、极简原型、极轻量的 webhook 服务 → Express 足够。
步骤 5:在路线图上找到它的位置 NestJS 处在 Node.js 路线图里「框架」这一进阶节点上,前置知识是 Node 基础与 TypeScript。本门课把这个节点展开成 12 节可跟做的精讲:从装环境到交付一个带校验、鉴权、测试的刷题平台 API。
讲清楚要点
大项目需要强制约定 :Nest 用 Module 明确分包边界,而不是靠文件夹命名的默契。
测试需要可替换的依赖 :业务类标记为 @Injectable 并由容器注入,单测时可以轻松换成 mock 实现。
路由需要可扫描的声明 :@Get、@Post 等装饰器让路由与类方法绑定,和 Spring MVC 的写法思路一致。
底层仍是 Node HTTP :你学过的 Express 中间件、异步流、事件循环知识全部有效,Nest 只是上层骨架。
本站语境下重点是模式迁移 :Controller / Service / Guard / Pipe 与 Spring 概念一一对应,学会对比比背 API 更重要。
性能适配器可选 :入门用默认 Express 适配器;真遇到吞吐瓶颈,再评估 Fastify 适配器的切换成本。
你可能会懵的地方
NestJS 是不是另一个 Express?
不是。它默认以 Express 为 HTTP 引擎,但在上面加了 DI 容器、模块系统和 Guard/Pipe/Interceptor。类比:Express 是发动机,Nest 是包含底盘和电路的整车。
装饰器难不难?要不要自己造?
初学者在入门阶段只会用官方提供的 @Controller、@Get、@Injectable 就够了;自定义装饰器是后面课程的内容,不需要一上来就研究原理。
听说它和 Angular 很像?
作者确实受 Angular 启发,Module、DI、装饰器风格接近。做过 Angular 的人会上手很快;没做过也完全不影响学习。
必须先会 Spring 才能学 Nest 吗?
不必。对照 Spring 只是帮助有 Java 基础的读者加速理解;会 Express 加 TypeScript 就能开始。
DI 容器里到底装了什么?
默认情况下,每个被注册的 Provider 在整个应用中是单例,容器启动时(或首次使用时)创建实例,解析控制器构造器时按类型取出并注入。
错法对照 错法 问题 正解 把 Nest 理解为「用来淘汰 Express 的新运行时」 概念错误,排查方向会偏 它是 Node 之上的组织框架,底层常仍是 Express 在 Controller 里写业务并 new QuestionsService() 绕过容器,难以测试和替换 构造器注入 + 在 Module 注册 只抄装饰器、不懂 Module 装配 启动必报「无法解析依赖」 先学会 providers / imports / exports 认为会了 Nest 就该把本站 Java 全部重写 脱离团队语言与生态实际 按场景选型,Spring 仍是本站主栈 一上来就纠结 Express 还是 Fastify 在不重要的点上耗时 默认适配器入门,有性能数据再切换
卡点急救
看文档全是术语读不下去 :先抓住「一个类管路由、一个类管业务、一张清单把它们组装起来」这三句话,术语会在后续课程逐个落地。
担心 TypeScript 不够好 :能定义 interface、给函数参数标类型、看懂泛型即可开始;框架代码本身就是最好的 TS 教材。
不确定项目适不适合 Nest :问三个问题——路由是否超过十个、是否多人协作、是否需要自动化测试。三个都答「是」,Nest 的收益就很明显。
面试常问
NestJS 相比 Express 的核心优势是什么?
开箱即用的模块化架构、依赖注入、Guard/Interceptor/Pipe 等标准化横切能力;代价是更多概念和样板代码。小项目 Express 更轻快,中大型团队项目 Nest 更可维护。
NestJS 的依赖注入和 Spring 的 IoC 是一回事吗?
思想一致:类不主动创建依赖,而是声明需求、由容器注入。差别在于 Nest 主要靠 TypeScript 构造器类型与装饰器元数据,且模块可见性需要显式 exports,不像 Spring 靠包扫描默认全局可见。
NestJS 默认基于哪种 HTTP 库?
默认是 Express,通过平台适配器封装;也可以用 @nestjs/platform-fastify 切换到 Fastify,业务代码基本不变。
自测三问
一次请求进入 Nest 后,Guard、Pipe、Controller、Service 的先后顺序是什么?
@Injectable 大致对应 Spring 的哪个注解?它解决什么问题?
什么场景下你仍然会选择 Express 而不是 NestJS?
小结一句话 NestJS 是 TypeScript 语言里带模块化和依赖注入的企业级 Node 后端框架,骨架对标 Spring,底层仍是 Node。
延伸