AI全栈入门指南:使用 NestJs 创建第一个后端项目

大家好 👋,我是 Moment,目前正在使用 Next.js、NestJS、LangChain 开发 DocFlow。这是一个面向 AI 场景的协同文档平台,集成了基于 Tiptap 的富文本编辑、NestJS 后端服务、实时协作与智能化工作流等核心模块。

在这个项目的持续打磨过程中,我积累了不少实战经验,不只是 Tiptap 的深度定制、编辑器性能优化和协同方案设计,也包括前端工程化建设、React 源码理解以及复杂项目架构实践。

如果你对 AI 全栈开发、文档编辑器、前端工程化或者 React 源码相关内容感兴趣,欢迎添加我的微信 yunmz777 一起交流。觉得项目还不错的话,也欢迎给 DocFlow 点个 star ⭐

前两篇把认知铺好了,这一篇进入上手阶段。

如果你是第一次接触 NestJS,最推荐的方式不是手动搭目录,而是直接使用官方 CLI 创建项目。原因很简单,CLI 不只是帮你生成几个文件,它还会顺手把一个标准可运行的项目骨架搭好。这样你第一次接触时,不会一上来就被配置细节打断。

下面的示例统一使用 pnpm。如果你平时用的是 npmyarn,只要把命令替换成自己习惯的包管理器即可。

在终端中执行下面这条命令,就可以创建一个新的 NestJS 项目:

shell 复制代码
pnpm dlx @nestjs/cli new hello-nest

执行之后,CLI 会提示你选择包管理器。直接选择自己当前项目里最常用的那个就行。如果你平时主要使用 pnpm,这里继续选 pnpm 会更顺手。

这一步完成之后,你会得到一个已经初始化好的项目目录。依赖会自动安装,基础文件也会一并生成,所以不需要你再从零创建入口文件、路由文件和配置文件。

如果你之前没有用过 dlx,可以把它理解成临时拉起来跑一下某个命令行工具,不必先全局安装 @nestjs/cli,用完就走,比较适合第一次体验。

认识默认目录结构

项目创建完成后,先不要急着写代码。更重要的是先看一眼默认目录结构,因为这会直接帮助你理解 NestJS 是怎么组织应用的。

一个刚创建出来的项目,核心目录大致会像下面这样:

第一次看这些文件时,可以先抓最重要的几个:

  • src/main.ts 是应用入口,负责把整个 NestJS 应用启动起来
  • src/app.module.ts 是根模块,用来组织当前应用的基础结构
  • src/app.controller.ts 是控制器,负责接收请求和返回结果
  • src/app.service.ts 是服务层,负责承载具体业务逻辑

你会发现,哪怕只是一个最简单的 Hello World 项目,NestJS 也没有把所有逻辑都塞进一个文件里。它一开始就把入口、模块、控制器、服务拆开了。这正是前面提到的结构约束。

也就是说,NestJS 希望你从第一个项目开始,就用一种更接近真实业务系统的方式来组织代码,而不是先随便写,等项目变大后再重构。

如果你现在只记一句话,可以先记这个:

src/main.ts 负责启动,Module 负责组织,Controller 负责接请求,Service 负责写逻辑。

后面无论项目变得多复杂,这套基础分工都不会变。

启动开发环境

进入项目目录后,就可以把开发环境跑起来了:

shell 复制代码
cd hello-nest
pnpm run start:dev

这条命令会以开发模式启动项目,并开启监听。也就是说,你修改 src 里的代码后,服务通常会自动重新编译并重启,不需要你每次手动停掉再启动。

项目启动成功后,终端一般会看到类似 Nest application successfully started 的提示。默认情况下,服务会监听 3000 端口。

这时候你可以先用浏览器打开下面这个地址:

text 复制代码
http://localhost:3000

如果一切正常,你会看到默认返回的 Hello World!。这说明项目已经跑起来了。

这一步的意义不只是确认环境没问题,更重要的是让你先建立一个非常直接的印象:

一个刚生成出来的 NestJS 项目,本身就是可运行的。

也正因为默认项目能立刻跑起来,后面改代码时,你能很直观地对照改了哪个文件、行为发生了什么变化。

写第一个接口

默认项目已经有一个最基础的接口,只是它的业务非常简单。为了真正理解 NestJS 的组织方式,最好的做法不是新建一堆复杂模块,而是先把这个默认接口改一遍。

先看服务层。把 src/app.service.ts 改成下面这样:

typescript 复制代码
import { Injectable } from "@nestjs/common";

@Injectable()
export class AppService {
  getHello(): { message: string; from: string } {
    return {
      message: "Hello NestJS",
      from: "AppService",
    };
  }
}

这段代码的重点不是返回什么内容,而是让你看到,真正的业务结果是由 AppService 提供的。控制器不直接写死所有内容,而是去调用服务层。

接着修改 src/app.controller.ts

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

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get("hello")
  getHello(): { message: string; from: string } {
    return this.appService.getHello();
  }
}

这里有两个点值得第一次接触时特别留意。

第一,@Controller()@Get("hello") 这类装饰器,标的是这个类、这个方法在 HTTP 这一层各自干什么。

第二,控制器通过构造函数拿到 AppService,而不是自己手动 new AppService()。这就是依赖注入最直观的体现。你声明自己需要什么,框架负责把依赖准备好。

改完之后,重新访问下面这个地址:

text 复制代码
http://localhost:3000/hello

如果一切正常,你会看到类似下面这样的返回结果:

看到这里,其实你已经完成了自己的第一个 NestJS 接口。虽然它非常简单,但最关键的骨架已经出现了。

从 Hello World 看 NestJS 的基本组织方式

一个最简单的 Hello World 也能看出 NestJS 的分层习惯,请求不会随便落进某个函数,而是按约定往前走。最短路径可以先想成下面五步:

  • 客户端发起请求
  • 路由命中控制器方法
  • 控制器调用服务层
  • 服务层返回业务结果
  • 框架把结果写回客户端

在这五步之上还要叠上两块,根 Module(例如 AppModule)把 ControllerService 登记到同一个模块里,src/main.ts 创建应用实例并监听端口,进程才真正跑起来。接请求、写业务、做装配、拉起监听,是同一条最小链路上的不同环节。

对应到代码里,先记住四个角色就够:

  • Controller 接住请求
  • Service 处理业务
  • Module 把相关角色收进同一个模块
  • src/main.ts 把应用跑起来并监听端口

这和先把逻辑全塞进一个文件再说的写法差别很大,NestJS 从第一个接口就在推你把入口、业务和装配拆开。返回值具体写了哪句文案反而不那么重要,更值得留意的是三件事已经成习惯:入口和业务分开、依赖交给框架装配、结构按角色长而不是按临时想法堆。

把这条轮廓记熟,后面再学模块拆分、参数校验、异常处理、数据库接入,都容易挂回同一套形状里。

小结

第一个 NestJS 项目的重点,不是把服务跑起来本身,而是借这个最小示例看清它的基本骨架。

通过 CLI 创建项目,你拿到的是一套标准初始结构。通过修改默认接口,你能看到 ControllerService、依赖注入和应用入口是如何协同工作的。

如果你现在已经能理解下面这几件事,这一篇的目标就达到了:

  • 如何用 CLI 创建一个 NestJS 项目
  • 默认目录里几个核心文件分别负责什么
  • 怎样启动开发环境并访问默认服务
  • 怎样改出自己的第一个接口
  • 为什么这个最小例子已经体现了 NestJS 的基本组织方式

接下来会从这个最小项目出发,看 Controller 和路由是怎么对应起来的。

相关推荐
巫山老妖2 小时前
🧪 AI+测试:当AI遇上软件测试,效率提升10倍不是梦!
前端
希望永不加班2 小时前
SpringBoot 定时任务:@Scheduled 基础与动态定时
java·spring boot·后端·spring
我叫黑大帅2 小时前
如何设计应用层 ACK 来补充 TCP 的不足?
后端·面试·go
AIUCE2 小时前
我给 AI 装了个"秦始皇":11 层架构解决 AI 黑箱问题
后端
蜡台2 小时前
Vue3 props ref router 数据通讯传输等使用记录
前端·javascript·vue.js·vue3·router·ref
SimonKing2 小时前
每天白送4000万Token!这款“龙虾”AI神器,微信就能操控电脑
java·后端·程序员
Cobyte2 小时前
从 JavaScript 的角度理解 Python 语法
前端
travel_wsy2 小时前
vue Pinia 状态管理库
前端·pinia
巫山老妖2 小时前
📐 Embedding向量化:AI如何「理解」语义?万物皆可向量!
前端