CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
NestJS 实战入门/课时/项目创建与结构
RawBlame
课时目录12 节

NestJS 实战入门

  1. 01NestJS 是什么
  2. 02项目创建与结构
  3. 03Module 与依赖注入
  4. 04Controller 与路由
  5. 05Service 层
  6. 06Pipe 与校验
  7. 07Guard 与认证
  8. 08ConfigModule
  9. 09数据库接入入门
  10. 10异常与过滤器
  11. 11测试
  12. 12综合练习

项目创建与结构

Nest CLI、module/controller/service 目录、dev 启动。

30 分钟

项目创建与结构

这一课你将能做到

  1. 用 Nest CLI 创建刷题平台项目 quiz-api,并通过 npm run start:dev 看到第一个响应
  2. 指认 main.ts、AppModule、AppController、AppService 各自管什么
  3. 修改返回内容与监听端口,验证热重载;看懂 package.json 里的脚本分工

为什么要学

Nest 官方推荐用 CLI 生成骨架,而不是从零手搭 tsconfig.json、Jest、目录约定。

人话:CLI 帮你铺好「能跑、能测、能编译」的地板,后面的课只往上加业务模块。不了解结构会出现三类典型问题:改错入口文件、不知道 Service 该登记在哪、生产环境直接用 ts-node 硬跑源码。花十分钟认清骨架,后面省几小时。

先建立图像

nest new quiz-api
        │
        ▼
src/
  main.ts              ← 启动入口:创建应用、监听端口
  app.module.ts        ← 根模块:imports / controllers / providers
  app.controller.ts    ← 示例 HTTP 入口
  app.service.ts       ← 示例业务类
test/                  ← e2e 测试目录
nest-cli.json          ← CLI 编译与资源规则
tsconfig.json          ← TypeScript 配置(含装饰器开关)
package.json

与 Spring Boot 的直觉对照:

NestJSSpring Boot
main.ts 的 bootstrap()public static void main
AppModule@SpringBootApplication 配置起点
npm run start:devmvn spring-boot:run
dist/main.js打包后的可执行 jar
nest generateSpring Initializr / IDE 代码生成

跟着做

步骤 1:安装 CLI 并创建项目

在终端执行(Node.js 18+):

npm install -g @nestjs/cli
nest new quiz-api

包管理器提示时选择 npm;新版本 CLI 默认开启 strict TypeScript,直接保留。然后:

cd quiz-api
npm run start:dev

浏览器打开 http://localhost:3000,应看到 Hello World!;终端同时打印 Nest 的启动日志和路由映射表 RouterExplorer。

步骤 2:读懂 main.ts 启动链

打开 main.ts,CLI 生成的内容大致是:

import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";

async function bootstrap() {
  // 人话:用根模块创建一个 Nest 应用实例
  const app = await NestFactory.create(AppModule);
  // 人话:监听端口,优先使用环境变量 PORT
  await app.listen(process.env.PORT ?? 3000);
}
bootstrap();

这里没有任何业务逻辑,只有「创建容器 + 监听端口」。以后的全局前缀、全局 Pipe、全局过滤器也都注册在这个文件里。

步骤 3:改 Service,确认热重载生效

打开 src/app.service.ts:

import { Injectable } from "@nestjs/common";

@Injectable()
export class AppService {
  getHello(): string {
    // 人话:先返回纯文本,后续课程换成题目 JSON
    return "刷题平台 API 已就绪";
  }
}

保存后观察终端:start:dev 会自动重新编译并重启。刷新浏览器即可看到新文案。若没变化,确认你改的是 src/ 下的文件且 dev 进程仍在运行。

步骤 4:认清 AppModule 的装配清单

打开 src/app.module.ts:

import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";

@Module({
  imports: [], // 引入其他模块
  controllers: [AppController], // 本模块的 HTTP 入口
  providers: [AppService], // 本模块可注入的类
})
export class AppModule {}

人话:根模块告诉框架「有哪些控制器、有哪些可注入的类」。AppController 能注入 AppService,正是因为两者都登记在同一个 Module 里。

步骤 5:换端口启动一次

PowerShell:

$env:PORT=3001; npm run start:dev

macOS / Linux:

PORT=3001 npm run start:dev

访问 http://localhost:3001,应看到同样的响应。说明端口由环境变量控制,而不是写死的 3000。关闭该进程后继续。

步骤 6:看懂装饰器相关的编译配置

打开 tsconfig.json,确认这两个关键选项:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "target": "ES2021",
    "strict": true
  }
}

experimentalDecorators 让 @Controller() 这种写法生效;emitDecoratorMetadata 让容器在运行时还能读到构造器参数的类型——依赖注入靠的就是它。TypeScript 5 虽然已支持新标准装饰器,但 NestJS 10 的生态仍使用这套实验性装饰器,不要自行关掉。

步骤 7:跑一次生产构建

npm run build
npm run start:prod

build 会先把 TypeScript 编译到 dist/,start:prod 运行编译后的 JS。开发阶段用 start:dev,部署阶段用 build 加 start:prod——不要用开发模式扛生产流量。

讲清楚要点

  1. 约定大于配置:优先用 nest new 生成骨架,少手搓工具链,把时间花在业务上。
  2. 入口只做 bootstrap:main.ts 只负责创建应用和监听端口,业务逻辑下沉到模块树。
  3. 登记才能注入:Module 的 controllers / providers 是容器的装配清单,漏登记必然启动报错。
  4. dev 与 prod 分离:start:dev 监听文件变化、快速反馈;生产运行 dist/ 编译产物。
  5. 端口随环境变化:用 process.env.PORT,写死 3000 只适合本机演示,部署到平台时端口通常由平台分配。
  6. 装饰器依赖编译选项:删掉 emitDecoratorMetadata,按类型自动注入就会失灵。

你可能会懵的地方

  • nest 命令找不到怎么办? 全局安装失败或 PATH 没刷新。可以直接用 npx @nestjs/cli new quiz-api,效果相同。

  • 端口 3000 被占用? 换 PORT=3001 启动,或关掉占用 3000 的旧 Node 进程。Windows 可用 netstat -ano | findstr :3000 查进程。

  • 改了代码浏览器仍旧? 看终端是否编译成功;存在 TS 错误时,热重载会停在上一次成功的产物,并不会强行启动坏代码。

  • AppController / AppService 能删吗? 可以,随业务模块逐步替换;但建议保留一个可响应的路由(如 /api/health)做存活探测。

  • strict 模式红线太多? 保留它。初学者可以把红线当成编译器在现场教学:它在逼你明确契约;到处用 any 逃避,只会把坑留到联调阶段。

错法对照

错法问题正解
手动建空文件夹当项目缺 Jest、tsconfig、CLI 配置nest new quiz-api
生产环境跑 start:dev热重载开销、体积与安全风险npm run build + start:prod
业务全写进 main.ts无法模块化、无法测试bootstrap 之外的逻辑全部下沉
Service 忘记放进 providers注入失败、启动报错在 Module 中登记
关掉 emitDecoratorMetadata容器读不到参数类型保留 CLI 生成的 tsconfig

卡点急救

  1. 安装 CLI 卡住或超时:切换 npm 镜像(如 npm config set registry https://registry.npmmirror.com),或用 npx 免全局安装。
  2. 启动报 EADDRINUSE:端口被占,换 PORT 启动;或在任务管理器结束残留的 node 进程。
  3. 热重载不触发:确认使用的是 start:dev 而非 start;公司同步盘(OneDrive 等)可能干扰文件监听,把项目放到普通本地目录。

面试常问

  • Nest 应用的启动流程是什么? main.ts 调用 NestFactory.create(AppModule),框架实例化 DI 容器、解析模块树、注册控制器与路由,最后 listen 端口。对应 Spring Boot 从主类启动并初始化 ApplicationContext。

  • 为什么生产环境不直接跑 TypeScript 源码? 源码需要即时编译,启动更慢、内存更高,也依赖开发依赖。正式部署先编译为 JS 再用 Node 运行,产物确定、可复现。

  • start:dev 的热重载是怎么实现的? CLI 内部用 watch 模式监听 src/ 文件变化,增量重编译后自动重启应用;它是开发效率工具,不用于生产。

自测三问

  1. main.ts 和 AppModule 分别解决什么问题?
  2. 为什么修改 AppService 后,浏览器刷新就能看到新结果?
  3. start:dev 和 start:prod 各适合什么阶段?差别在哪?

小结一句话

Nest CLI 生成可运行的工程骨架:main 负责启动,AppModule 负责装配,dev 热重载、prod 跑 dist。

延伸

  • First steps(官方入门步骤)
  • CLI Overview(命令一览)
  • 下一课预告:用 CLI 生成题库模块,理解 Module 边界与依赖注入,并故意制造一次「未注册 Provider」报错。
加载本节练习…
← 上一课NestJS 是什么下一课 →Module 与依赖注入