我是如何学习 NestJS 的

0 阅读11分钟

写在前面

作为一名前端开发者,虽然日常工作都围绕着浏览器这一端打转,但我始终觉得:一个真正意义上的程序员,不应该只停留在某一层的舒适区里,而应该对一个系统从请求进来到数据落盘的整条链路都有所理解。正是带着这样的想法,我开始寻找一门能够让我系统性进入后端世界的框架,最终锁定了 NestJS

为什么是 NestJS,而不是 Java?

在选择技术栈时,我其实也认真考虑过 Java。毕竟 Java 在后端领域几乎等于"标配",岗位多、生态全、体系成熟。但对我这样一个后端基础相对薄弱的前端选手来说,Java 的学习曲线实在有些陡峭:

  • 不仅要学习语言本身,还要吃透 JVM、Maven/Gradle、Spring 全家桶等一整套生态;
  • 对于几乎没有"后端感觉"的我来说,直接从 Java 入门,很可能在门口就被劝退。

相比之下,NestJS 对我来说几乎是"量身定制"的选择:

  • 它基于我最熟悉的 TypeScript,语言层面几乎零成本;
  • 它借鉴了 Angular 的 依赖注入 / 模块化 思想,架构设计足够"后端范儿";
  • 它的分层结构足够清晰,可以帮助我快速建立起后端工程的思维模型。

更重要的一点是,先用 NestJS 把后端的通用概念跑通,未来如果再切换到 Java,剩下的就只是语言层面的迁移成本了,这笔账怎么算都划算。

我的学习路径

最初我其实也想过"B 站大学"速成一波。但转念一想,视频教程存在两个问题:一是内容未必跟得上 NestJS 11 这一版本的变化,二是被动听讲的效率对我来说偏低。于是我最终选择了最朴素、也最有效的方式——直接啃官方文档

整个过程坦白说并不轻松:

  • 文档全程英文,很多概念第一次接触,需要反复查阅;
  • Nest 背后牵扯着 IoC、装饰器元编程、RxJS、中间件/管道/守卫/拦截器等一串陌生词汇;
  • 阅读过程其实相当枯燥,很多时候一个小节要看两三遍才能真正理解。

支撑我一路啃下来的,其实是好奇心:每学到一个新概念,我都会忍不住去想"那再往下一层是什么?",这种"下一步会出现什么"的期待感,比任何计划表都更有效。老实说,如果没有这份好奇心驱动,我大概坚持不了几天就会放弃。

文档看完,只是拿到了"门票"。真正把知识变成自己的东西,还得靠写代码。 于是我开始在 GitHub 上翻阅现成的 NestJS 项目,也认真参考了后端同学熟悉的 若依(RuoYi) 框架。几番对照之后,我给自己定了一个目标:做一个 NestJS 版本的类若依项目,把认证授权、权限管理、安全防护、监控审计等企业级能力完整地跑一遍。

这也成为了我目前投入时间和精力最多的一个个人项目,甚至超过了当初学 Next.js 的那段时间——说实话,Next.js 的文档同样并不好啃,但 NestJS 这次是连"后端通识"也得一起补上。

技术选型的一些波折

由于市面上并没有太多可以直接抄作业的"企业级 NestJS 模板",项目初期的技术选型几乎全靠自己一个个调研试错。经过反复权衡,我最终选择了这样一套组合:

PostgreSQL + Prisma ORM + Redis

其中 Prisma 是整个项目里让我又爱又恨的一环:它的类型推导和迁移体验堪称一绝,但在一些复杂场景(比如多表事务、软删除与唯一索引冲突、嵌套关系过滤)下也确实踩了不少坑。好在这些问题最终都找到了各自的解决方案,也正因为踩过这些坑,模板里才沉淀了一些相对完整的实践姿势。

具体的踩坑过程这里就不展开了(字太多大家看着也累 😅),下面直接来看最终成果。

项目相关信息

仓库地址:github.com/dyb-dev/nes…

这是一套基于 NestJS 全家桶 搭建的企业级后端开发模板,目标是让团队拿到手就能用在真实的生产项目里,而不是"一个跑起来的 Hello World"。

一、整体架构

在模块组织上,项目采用了 六层模块化 的设计,每一层的职责边界都尽量清晰:

层级职责
auth认证授权,包括登录、登出、令牌签发与刷新
core核心基础设施,封装数据库(Prisma)、缓存(Redis)、日志(Pino)
shared通用共享服务,如验证码、加解密、CSRF、权限、文件、IP 定位、UA 解析等
system业务系统域,包括用户、角色、菜单、部门、岗位、字典、通知、参数配置等
monitor监控审计,包括在线会话、登录日志、操作日志、缓存监控、服务器监控等
scheduler任务调度,统一管理定时任务与任务执行日志

在单个业务模块内部,则严格遵循 Controller / DTO / Module / Repository / Service 的五层结构,保证任意一个模块打开都是熟悉的样子,降低团队协作成本。

二、数据层设计

  • 数据库选用 PostgreSQL 16,ORM 使用 Prisma 7.x,结合 @prisma/adapter-pg 驱动;
  • 缓存使用 Redis 7+,通过 cache-manager + @keyv/redis 实现多层缓存抽象,便于后续替换或扩展;
  • 事务方面基于 nestjs-cls + @nestjs-cls/transactional-adapter-prisma,实现了声明式事务,避免在 Service 层到处手动传 tx;
  • 所有业务实体统一采用基于时间戳的软删除,既满足数据审计诉求,也巧妙规避了传统软删除与唯一索引之间的冲突问题。

三、认证授权与安全体系

这一块是我在项目里投入最多精力的部分,也是模板相比脚手架最大的价值所在:

  • 双令牌认证:Access Token + Refresh Token 分离签发,短期令牌保证安全性,长期令牌提升体验;
  • RBAC 鉴权:基于「角色 + 权限标识」设计,配合自定义装饰器与守卫实现接口级鉴权;
  • 端到端加解密:采用 RSA + AES 混合加密方案,对请求体和响应体进行加解密,适合对敏感数据有强要求的业务场景;
  • CSRF 防护:使用 csrf-csrf 实现 Double Submit Cookie 方案;
  • 防重放攻击:基于 x-timestamp + x-nonce 的校验机制,防止接口请求被抓包后回放;
  • 接口限流:使用 @nestjs/throttler 按 IP/用户维度进行限流;
  • HTTP 安全响应头:通过 Helmet 统一加固;
  • 密码存储:使用 bcrypt 加盐哈希,杜绝明文风险;
  • 敏感字段脱敏:通过全局拦截器对手机号、邮箱等敏感字段自动脱敏,避免日志与接口泄露;
  • 会话集中管理:登录会话集中存储在 Redis 中,支持管理员主动将用户强制下线。

四、基础设施与工具链

模板里内置了一整套开箱即用的基础设施,让你不需要再花时间去"搭架子":

  • 结构化日志:使用 nestjs-pino,开发环境美化输出、生产环境按日期滚动归档;
  • 消息队列:集成 BullMQ,基于 Redis 提供可靠的异步任务能力;
  • 定时任务:使用 cron,将系统任务与业务任务统一纳入调度模块,并输出任务执行日志;
  • HTTP 客户端:封装 @nestjs/axios,全局统一超时、重试、错误处理策略;
  • 文件上传:内置 multer,并配套静态资源托管能力;
  • 图形验证码:基于 svg-captcha 生成 + 服务端校验;
  • 真实 IP 识别:使用 request-ip + ipaddr.js,兼容各种反向代理场景;
  • UA 解析:通过 ua-parser-js 识别浏览器与操作系统,用于登录日志记录;
  • 服务器监控:借助 systeminformation 获取 CPU、内存、磁盘等实时指标,配合健康检查接口对外暴露。

五、统一的工程约定

一个模板之所以是"模板",在于它规定了团队协作时的共识。我为这个项目沉淀了以下几条约定:

  • 全局异常过滤器:统一捕获业务异常、参数异常、系统异常,避免到处 try/catch;
  • 统一响应码体系:通过通用 DTO 封装响应结构,确保所有接口输出格式一致;
  • 通用 DTO 组件:响应、分页、加解密、验证码等场景都提供了开箱即用的 DTO;
  • 装饰器 / 守卫 / 管道 / 拦截器 / 中间件:按职责拆分到独立目录,便于在项目里快速定位与复用;
  • 路径别名:@/* 全项目生效,避免无意义的相对路径跳跃。

六、开发体验

工程化与开发体验同样不能将就:

  • 使用 Vite + vite-plugin-node + SWC 驱动开发热更新与生产编译,速度相比传统 ts-node 有明显提升;
  • 使用 ESLint + Prettier 双层规范化,并通过 Husky + lint-staged 在 Git 提交前自动检查与格式化;
  • 使用 @dyb-dev/project-cli 实现一键版本发布与 Git 打标;
  • 通过 .env / .env.development / .env.production 做多环境变量隔离,避免把生产密钥写进代码。

快速开始

你只需要几步就能把项目跑起来。

1. 准备运行环境

工具版本要求
Node.js>= 22.0.0
pnpm>= 8.15.5 < 10.0.0
PostgreSQL>= 16
Redis>= 7

2. 通过脚手架一键创建项目

项目已经接入了统一脚手架,不需要手动克隆仓库,只要执行:

pnpm create @dyb-dev/create-project@latest

然后在交互式命令行中选择 nest-server-template 模板即可。

3. 安装依赖并初始化数据库

cd your-project
pnpm install

# 执行数据库迁移并生成 Prisma Client
pnpm migrate:dev

# 初始化种子数据(会自动创建超级管理员)
pnpm db:seed:dev

4. 启动开发服务

pnpm dev

服务默认运行在 http://localhost:3000/api

种子数据会自动创建超级管理员账号,可直接登录:

  • 用户名:admin
  • 初始密码:Admin@123456

配置说明

项目统一通过 .env 文件管理环境变量,并按环境做了隔离:

# .env               全局公共配置
# .env.development   开发环境密钥与连接串
# .env.production    生产环境密钥与连接串

需要特别留意的是,模板中预置的 JWTRSAAESHMACCSRF 等密钥仅用于演示,在正式投入使用前必须全部替换为你自己的密钥,否则会带来严重的安全隐患。

一个模板,两种用法

这个项目从一开始就是以"开箱即用"为目标来设计的,所以它既可以作为 生产项目的起点,也可以作为 学习 NestJS 的参考对象:

  • 如果你正在启动一个新的后端项目,可以直接拿它作为底座,省去搭建认证、权限、日志、监控等一堆重复性工作的时间,把精力集中在真正的业务逻辑上;
  • 如果你和我一样,正处于学习 NestJS 的阶段,也完全可以把它当成一份"有完整业务场景的参考实现"来阅读。相比零散的官方示例,这里每一个模块都是围绕真实需求落地的,能更直观地帮助你理解 依赖注入、模块划分、守卫/拦截器/管道 等概念在工程里到底长什么样。

当然,目前的版本还远远谈不上"完整"。后续我计划继续迭代,打造一条更加顺滑的开发与部署流程,初步规划包括:

  • Nginx:统一反向代理、静态资源托管以及 HTTPS 配置的最佳实践;
  • Docker:提供一键本地环境与生产部署的容器化方案,让数据库、Redis、应用一起开箱即用;
  • Vitest:补齐单元测试与集成测试体系,让模板在"可维护"这件事上也有交代。

写在最后

以上就是我学习 NestJS 的整个过程,从一个对后端懵懵懂懂的前端开发者,到硬着头皮啃完官方文档,再到亲手做出一个类似若依的 NestJS 企业级模板——这段经历对我而言,意义远不止"掌握了一门新框架"那么简单,更重要的是让我第一次真正建立起了对后端工程的整体感觉。

当然,项目里一定还有许多可以打磨的地方,我自己也还在持续迭代。如果你在阅读代码或使用模板的过程中发现了问题,非常欢迎提 Issue 或 PR,也期待有经验的大佬能给我一些指点 🙏。

希望这篇文章和这个项目能对同样在尝试从前端走向全栈的你有所帮助。感谢你读到这里 ❤️。