当前位置: 首页 > news >正文

Nest.js 入门:从 0 到 1 掌握企业级 Node.js 框架(新手也能秒懂模块/控制器/服务)

还在被 Nest.js 的模块、控制器、提供者搞得晕头转向?想不通依赖注入如何工作,更不懂如何组织大型项目?

今天这篇教程,全程围绕 Nest.js 的核心架构展开,从基础原理到实战接口,手把手教你用 Nest.js 实现标准的 RESTful API,新手也能跟着敲出效果,彻底搞懂 Nest.js 在企业级开发中的核心作用。

1. 先搞懂:Nest.js + 架构设计 = 企业级 Node.js 应用的灵魂

Nest.js 是一个用于构建高效、可扩展的 Node.js 服务端应用的框架。它使用渐进式 JavaScript,构建在 TypeScript 之上,并且结合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数式响应式编程)的元素。

核心优势
  • 模块化架构:应用程序被组织成模块(Modules),每个模块封装相关的控制器、服务等,结构清晰,易于维护和扩展。

  • 依赖注入容器:内置强大的依赖注入(DI)系统,自动管理类的实例化和生命周期,降低代码耦合度。

  • 平台无关:可以基于 Express(默认)或 Fastify 运行,提供灵活的底层 HTTP 服务器适配。

  • 丰富的生态系统:提供大量官方和社区模块,如 TypeORM、Mongoose、GraphQL、WebSockets 等,开箱即用。

  • 支持多种传输层:不仅能创建 HTTP 服务,还能轻松构建 WebSocket 网关、微服务等。

2. Nest.js 核心概念与工作原理

Nest.js 的核心是控制器(Controllers)提供者(Providers)模块(Modules)。它们是构建任何 Nest.js 应用程序的基石。

  • 控制器:负责处理传入的请求并返回响应给客户端。它们通过装饰器(如@Controller@Get@Post)来定义路由和 HTTP 方法。

  • 提供者:负责处理具体的业务逻辑,可以被注入到控制器或其他提供者中。服务(Services)、存储库(Repositories)、工厂(Factories)等都属于提供者。它们通过@Injectable()装饰器标记。

  • 模块:使用@Module()装饰器来组织应用程序结构。每个模块是一个包含控制器、提供者等的容器,可以导入其他模块或导出自己的提供者供其他模块使用。

工作流程(以处理一个 HTTP 请求为例):

  1. 客户端发起一个 HTTP 请求到服务器(如GET /users)。

  2. 控制器中匹配到对应路由的处理器(Handler)被触发。

  3. 控制器调用提供者(如 UsersService)中的方法来执行实际的业务逻辑(例如从数据库查询用户)。

  4. 提供者执行逻辑并返回结果给控制器。

  5. 控制器将结果包装成 HTTP 响应发送回客户端

这个过程通过依赖注入无缝连接:Nest.js 运行时会自动将 UsersService 的实例注入到 UsersController 的构造函数中。

2.1 环境准备与项目创建

第一步:环境准备
确保你的开发环境中安装了Node.js(版本 20 或更高)。你可以使用node -v检查版本。

第二步:安装 Nest CLI
Nest CLI 是一个强大的命令行工具,可以帮助你快速搭建项目、生成代码文件等。

bash

npm i -g @nestjs/cli

第三步:创建新项目
使用nest new命令创建一个新项目,将my-nest-project替换为你想要的项目名称。

bash

nest new my-nest-project

CLI 会询问你希望使用哪种包管理器(npm、yarn 或 pnpm),选择你习惯的即可,如下图。

第四步:启动项目
进入项目目录并启动开发服务器。

bash

cd my-nest-project npm run start:dev

访问http://localhost:3000/,如果看到 “Hello World!”,说明项目已成功运行,如下图。

项目结构概览
创建好的项目结构大致如下:

text

my-nest-project/ ├── src/ │ ├── main.ts # 应用程序入口文件 │ ├── app.module.ts # 根模块 │ ├── app.controller.ts # 根控制器 │ └── app.service.ts # 根服务 ├── test/ # 测试文件夹 ├── package.json ├── tsconfig.json └── ...

3. 代码详细解释

核心文件协作流程图

为了更直观地理解这些文件如何协同工作,请看下图:

流程简述:

  1. main.ts启动应用,加载AppModule

  2. AppModule声明了控制器AppController和服务AppService

  3. 当客户端访问根路径时,AppControllergetHello方法被调用。

  4. 控制器通过依赖注入调用AppServicegetHello方法获取数据。

  5. 服务返回字符串,控制器将其作为 HTTP 响应发送给客户端。

我们已经成功创建并运行了一个 Nest.js 项目。但你是否对src文件夹下自动生成的几个核心文件感到好奇?它们各自扮演什么角色?又是如何协作的?本节将带你逐一拆解,彻底搞懂 Nest.js 应用的骨架。

  • main.ts是启动入口,负责创建应用和监听端口。

  • app.module.ts是根模块,负责组织其他组件。

  • app.controller.ts处理具体路由,接收请求并调用服务。

  • app.service.ts封装业务逻辑,可被注入。

  • app.controller.spec.ts确保控制器按预期工作。

下面我们逐个深入解析。


1.main.ts—— 应用程序的启动入口

main.ts是整个 Nest.js 应用的起点,它负责启动应用并监听端口。其典型代码如下:

typescript

import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); // ① 创建应用实例 await app.listen(process.env.PORT ?? 3000); // ② 监听端口 } bootstrap(); // ③ 启动函数调用

代码详解:

  • NestFactory.create(AppModule):这是创建 Nest 应用实例的核心方法。它接收一个根模块AppModule)作为参数,Nest 会根据这个模块的配置(导入的模块、控制器、提供者等)来组装整个应用。这里创建的应用默认基于 Express 引擎。

  • app.listen(3000):启动 HTTP 服务器,监听 3000 端口。你可以修改为任何可用端口,或者从环境变量中读取(如process.env.PORT)。

  • bootstrap():调用异步启动函数,让应用跑起来。

扩展知识:你可以在main.ts中进行一些全局配置,例如:

  • 使用全局前缀:app.setGlobalPrefix('api')会使所有路由自动加上/api

  • 启用 CORS:app.enableCors()

  • 添加全局验证管道:app.useGlobalPipes(new ValidationPipe())

  • 配置静态文件服务等。


2.app.module.ts—— 根模块

模块是 Nest.js 组织代码的基本单位。app.module.ts是应用的根模块,它将所有其他模块和组件汇聚在一起。其典型代码如下:

typescript

import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [], // ① 导入其他模块 controllers: [AppController], // ② 声明本模块中的控制器 providers: [AppService], // ③ 声明本模块中的提供者(服务) }) export class AppModule {}

代码详解:

  • @Module()装饰器:用于定义模块,它接受一个描述模块元数据的对象。

  • imports数组:导入其他模块,以便在当前模块中使用它们导出的提供者。初始项目为空,随着功能增加,你会在这里导入UsersModuleDatabaseModule等。

  • controllers数组:声明该模块下所有的控制器。Nest 会实例化这些控制器并注册路由。

  • providers数组:声明该模块下所有的提供者(通常是服务)。Nest 会将这些提供者放入依赖注入容器,使得它们可以被控制器或其他提供者注入。

关键点:根模块负责引导整个应用。如果你创建了功能模块(如UsersModule),需要将其导入到imports数组中,这样应用才能识别该模块的组件。


3.app.controller.ts—— 根控制器

控制器负责处理特定路径的 HTTP 请求。app.controller.ts是默认生成的根控制器,它定义了一个简单的 GET 路由。典型代码如下:

typescript

import { Controller, Get } from '@nestjs/common'; import { AppService } from './app.service'; @Controller() // ① 基础路由前缀(此处为空) export class AppController { constructor(private readonly appService: AppService) {} // ② 注入 AppService @Get() // ③ 处理 GET 请求,路径为 '/'(因为控制器前缀为空) getHello(): string { return this.appService.getHello(); // ④ 调用服务中的方法 } }

代码详解:

  • @Controller()装饰器:标记该类为控制器,可以传入一个字符串作为路由前缀,例如@Controller('users')会使该控制器内的所有路由都加上/users前缀。这里为空,表示基础路径为/

  • ② 构造函数注入:通过声明private readonly appService: AppService,Nest 会自动从依赖注入容器中提供AppService的实例。这是依赖注入的典型用法。

  • @Get()装饰器:修饰getHello方法,表示该方法处理 HTTP GET 请求。因为没有指定具体路径,所以它处理的是控制器基础路径(即/)的 GET 请求。

  • ④ 业务逻辑委托:控制器本身不应包含复杂业务逻辑,而是调用服务(AppService)的方法,将结果返回。

运行效果:当你访问http://localhost:3000/时,该方法被调用,返回字符串 "Hello World!"。


4.app.service.ts—— 根服务

服务(提供者)负责处理具体的业务逻辑,可被注入到控制器或其他服务中。app.service.ts的典型代码如下:

typescript

import { Injectable } from '@nestjs/common'; @Injectable() // ① 标记该类为可注入的提供者 export class AppService { getHello(): string { // ② 业务方法 return 'Hello World!'; } }

代码详解:

  • @Injectable()装饰器:告诉 Nest 这个类是一个提供者,可以被依赖注入系统管理。只有添加了该装饰器的类才能被注入到其他类中。

  • getHello()方法:简单的业务逻辑方法,返回一个字符串。在真实项目中,这里可能会调用数据库、调用其他 API 等。

注意:服务通常不直接处理 HTTP 细节(如状态码、请求头),这些应该由控制器负责。服务专注于业务逻辑,使其更易于测试和复用。


5.app.controller.spec.ts—— 控制器的单元测试

Nest.js 鼓励编写测试,并自动生成了控制器的测试文件。app.controller.spec.ts是一个使用 Jest 框架的单元测试示例:

typescript

import { Test, TestingModule } from '@nestjs/testing'; import { AppController } from './app.controller'; import { AppService } from './app.service'; describe('AppController', () => { let appController: AppController; beforeEach(async () => { const app: TestingModule = await Test.createTestingModule({ controllers: [AppController], providers: [AppService], }).compile(); appController = app.get<AppController>(AppController); }); describe('root', () => { it('should return "Hello World!"', () => { expect(appController.getHello()).toBe('Hello World!'); }); }); });

代码详解:

  • Test.createTestingModule():创建一个用于测试的模块,模拟了 Nest 的模块系统。我们传入与生产环境相同的控制器和提供者。

  • .compile():编译测试模块,实例化其中的组件。

  • app.get<AppController>(AppController):从测试模块中获取AppController的实例。

  • 测试用例:调用appController.getHello()并验证返回值是否为'Hello World!'

重要性:单元测试确保控制器在隔离环境下正确工作。你可以运行npm run test来执行测试。


小结

  • main.ts是启动入口,负责创建应用和监听端口。

  • app.module.ts是根模块,负责组织其他组件。

  • app.controller.ts处理具体路由,接收请求并调用服务。

  • app.service.ts封装业务逻辑,可被注入。

  • app.controller.spec.ts确保控制器按预期工作。

理解这五个核心文件,你就掌握了 Nest.js 最基本的 MVC 架构。随着项目增长,你会在src下创建更多模块(如users),每个模块都会包含类似的controllerservicemodule和测试文件。这种高度结构化的设计,使得 Nest.js 项目在变得庞大后依然清晰、可维护。

4.错误处理Failed to execute command: git git init Git repository has not been initialized

安装完成后,提示Failed to execute command: git git init Git repository has not been initialized。这个错误,是因为git没有安装

解决方案,新建项目时增加--skip-git 参数,或者安装git

nest new 项目名称 --skip-git
http://www.jsqmd.com/news/497931/

相关文章:

  • AI之Transform encoder/decoder抽象理解
  • 2026年多账号运营下浏览器指纹关联风险与防护方案研究
  • 【C语言学习笔记】(1)
  • 2026前端面试题和避坑指南
  • 风速仿真模型实现及代码详解
  • 吃透HTTP及相关协议核心区别,从基础到进阶全覆盖
  • 【AI】如何设计Agent的记忆系统?
  • 探索同城招聘系统源码:企业端+求职者端功能开发全流程详解
  • 阿里发布全球首个企业级Agent平台“悟空”,要把“龙虾”装进2000万企业组织里
  • python+Ai技术的学生课外活动管理系统的数据可视化大屏分析系统 _
  • Mixture of Experts(MoE)
  • 808nm在生物医疗科研中的使用方法
  • 英伟达发布Groq 3 LPX推理加速器,瞄准AI基础设施下一战场
  • 【架构】-----Service 层代码太长太乱?试试这套 “见名知意” 的命名规范!
  • 中小企业为什么要重视业财一体化
  • 国内炒黄金的人多不多?炒现货黄金有什么门槛?
  • HBase在大数据领域海量数据存储的解决方案
  • 收藏 | 从零开始学LangGraph,构建能思考的Agentic RAG系统,小白也能轻松上手!
  • 2026高纯度Omega3鱼油推荐榜:高纯度深海鱼油、高纯度鱼油、深海鱼油软胶囊、降血脂鱼油、高纯度omega3选择指南 - 优质品牌商家
  • 2026年了,居然还有免费的BIM软件!
  • Nginx解决前端跨域问题
  • 【JUC并发 | 第八篇】AQS的底层原理
  • 金仓数据库在MySQL迁移中的实践复盘:某汽车集团近百套系统两周平滑替换路径
  • mysql数据库常规操作2
  • 北航软件工程[I.2] 个人作业:软件案例分析
  • 共享内存与进程间通信(IPC):提升TDengine时序数据库内部数据流转效率
  • TCP vs UDP 怎么选(偏实战:别背概念,用场景做决策)
  • 3月面了十几家前端岗后,我才知道大佬这份飞书题库的含金量
  • 求你了,别用 YYYY-MM-dd!
  • comsol 锂枝晶模型 此模型为多枝晶定向形核,可以直接拿来用,不用自己建模,三种物理场:相...