怎么使用 NestJS CLI 初始化项目并配置 TypeScript 开发环境

作者:岩茶

时间:2026-11-02

浏览:665

系统介绍如何使用官方 NestJS CLI 工具快速初始化工程,并深度解析 tsconfig.json、tsconfig.build.json 及 nest-cli.json 的协同机制与关键 TypeScript 编译选项配置。

文章目录

使用 NestJS 官方脚手架 @nestjs/cli 初始化项目,核心在于通过 nest new <project-name> 自动拉取标准的工程模板,并在生成代码后梳理好 tsconfig.json、tsconfig.build.json 与 nest-cli.json 之间的协同关系。针对实际业务需求,开启 TypeScript 的严格类型检查、正确配置反射元数据与路径别名,即可快速建立起兼顾开发热重载与干净生产发布的工程环境。

怎么使用 NestJS CLI 初始化项目并配置 TypeScript 开发环境
图 0:NestJS CLI 脚手架生成与 TypeScript 开发运行整体架构总览

一、准备工作与 NestJS CLI 安装策略

在初始化 NestJS 项目之前,操作系统需要具备合规的 Node.js 运行环境及相应的包管理器。NestJS 底层严重依赖现代 JavaScript 特性与 TypeScript 编译器,推荐使用 Node.js 18 或 20 以上的长期支持版(LTS)。

1. 环境版本核对

在终端中执行以下命令确认运行环境版本:

检查命令
node -v
npm -v
示例输出
v20.12.0
10.5.0

2. 全局安装与 npx 免安装调用辨析

官方文档通常推荐使用 npm i -g @nestjs/cli 进行全局安装。这种方式看似简单,在终端中输入 nest 即可调用,但在多项目协作中容易出现全局 CLI 版本与具体项目脚手架版本不匹配的问题。

因此,对于初始化新项目,更推荐直接借助 npx 执行临时调用:

执行命令(免全局安装)
npx @nestjs/cli new my-nest-app

npx 会在执行时自动拉取 @nestjs/cli 的最新稳定版本完成项目脚手架的创建,生成完毕后不会占用全局系统空间。项目创建完成后,后续所有的开发、编译与测试脚本均通过项目内部安装在 node_modules/.bin/nest 的局部 CLI 执行,彻底杜绝不同项目间的版本冲突。

二、使用 NestJS CLI 完整初始化项目步骤

执行初始化命令后,NestJS CLI 会引导完成包管理器的选择,并自动创建工程骨架、初始化 Git 仓库及安装依赖。

怎么使用 NestJS CLI 初始化项目并配置 TypeScript 开发环境
图 1:从环境检查到启动验证的四步操作流程图

第一步:执行项目创建命令

在目标工作目录下运行创建指令(以项目名 my-nest-app 为例):

执行命令
npx @nestjs/cli new my-nest-app

第二步:选择依赖包管理器

CLI 启动后会弹出交互式提示,要求选择依赖包管理器:

交互终端示例
? Which package manager would you love to use? (Use arrow keys)
❯ npm
  yarn
  pnpm

通过上下箭头键选择团队常用的包管理器。在现代 Node.js 开发中,pnpm 拥有更快的依赖安装速度与磁盘硬链接共享机制;若无特殊要求,选择标准的 npm 亦可。选定后按下回车,CLI 将自动创建目录并执行依赖安装。

第三步:验证生成的工程结构

依赖安装完成后,进入项目目录,CLI 生成的文件结构如下:

my-nest-app/
├── src/
│   ├── app.controller.spec.ts  # 控制器单元测试文件
│   ├── app.controller.ts       # 基础路由控制器
│   ├── app.module.ts           # 应用程序根模块
│   ├── app.service.ts          # 基础服务逻辑
│   └── main.ts                 # 应用程序入口函数
├── test/
│   ├── app.e2e-spec.ts         # 端到端(E2E)测试
│   └── jest-e2e.json           # E2E 测试配置
├── nest-cli.json               # Nest CLI 专属构建与项目配置文件
├── tsconfig.json               # TypeScript 基础编译与语言服务配置
├── tsconfig.build.json         # 针对生产编译排除测试的精简配置
└── package.json                # 项目依赖与运行脚本清单

第四步:启动开发服务并验证结果

进入项目文件夹并启动内置热重载开发服务器:

执行命令
cd my-nest-app
npm run start:dev
终端输出示例
[Nest] 18234  - 02/11/2026, 00:30:00 AM     LOG [NestFactory] Starting Nest application...
[Nest] 18234  - 02/11/2026, 00:30:00 AM     LOG [InstanceLoader] AppModule dependencies initialized +8ms
[Nest] 18234  - 02/11/2026, 00:30:00 AM     LOG [RoutesResolver] AppController {/}: +6ms
[Nest] 18234  - 02/11/2026, 00:30:00 AM     LOG [RouterExplorer] Mapped {/, GET} route +3ms
[Nest] 18234  - 02/11/2026, 00:30:00 AM     LOG [NestApplication] Nest application successfully started +2ms

此时打开浏览器或使用 curl http://localhost:3000,页面返回 Hello World!,说明基于 TypeScript 的 NestJS 基础环境已成功运行。

三、TypeScript 双层配置文件体系解析

初学者在查看 NestJS 生成的根目录时,常产生一个疑问:“既然项目中已经有了 tsconfig.json,为什么还要额外生成一个 tsconfig.build.json?两者合并成一个不行吗?”

怎么使用 NestJS CLI 初始化项目并配置 TypeScript 开发环境
图 2:tsconfig.json 与 tsconfig.build.json 的继承分工与执行调用模型

1. 双配置的职责分离逻辑

这种双层设计是 NestJS 团队为了区分开发环境类型检查与生产编译构建所做的精准划分:

  • tsconfig.json(基准根配置):定义了整套 TypeScript 语言规则,是 IDE(如 VS Code)提供语法高亮、自动补全、类型校验的唯一依据。同时,Jest 单元测试也基于该配置运行。因此,它必须覆盖项目内的所有源码以及所有的测试文件(包括 *.spec.ts)。
  • tsconfig.build.json(生产构建配置):通过 "extends": "./tsconfig.json" 继承全部语言特性,但通过 "exclude" 明确剔除了 node_modules、test、dist 和 **/*spec.ts。当执行 npm run build 时,Nest CLI 会显式调用该配置,确保产出的 dist/ 纯净紧凑,不包含测试用例与 mock 代码。
易混淆辨析:如果直接删掉 tsconfig.build.json 并修改构建命令去直接编译 tsconfig.json,虽然程序看似能跑起来,但会导致单元测试代码被一并编译进 dist/ 目录,不仅增大发布体积,而且一旦测试代码引用了仅在 devDependencies 中存在的 mock 库,在生产环境中直接启动将会引发找不到模块的致命运行时异常。

2. nest-cli.json 的协同机制

nest-cli.json 是连接 CLI 与 TypeScript 编译器的桥梁。默认生成的关键结构如下:

{
  "$schema": "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "deleteOutDir": true
  }
}

其中 "deleteOutDir": true 确保每次执行 npm run build 时自动清空历史 dist 产物,避免残留已删除的旧文件。此外,若后续需要启用插件(例如 Swagger 自动类型提取插件 @nestjs/swagger),也是在 nest-cli.json 的 compilerOptions.plugins 中统一挂载。

四、关键 TypeScript 编译选项调优与实战配置

尽管 NestJS CLI 默认配置已经能够运行基础服务,但在实际商业开发中,往往需要开启更严格的类型检查和工程路径别名。

怎么使用 NestJS CLI 初始化项目并配置 TypeScript 开发环境
图 3:装饰器元数据(Reflect Metadata)提取与依赖注入执行机制

1. 核心关键项:装饰器与元数据发射

打开根目录下的 tsconfig.json,有两个选项是 NestJS 的生命线,绝对不能关闭:

"experimentalDecorators": true,
"emitDecoratorMetadata": true,

原因解释:NestJS 的控制反转(IoC)和依赖注入容器严重依赖 TypeScript 的类型反射。当在构造函数中书写 constructor(private readonly userService: UserService) 时,TypeScript 编译器只有在 emitDecoratorMetadata: true 下,才会将 UserService 这个构造类型输出到编译后的 JS 元数据中(design:paramtypes)。如果关闭此项,NestJS 运行时将无法得知该参数的具体类型,导致报出 Nest can't resolve dependencies of the Controller (?) 的注入失败错误。

2. 严格模式设置:strict 与严格属性初始化的取舍

CLI 默认生成的配置往往设置了较为温和的检查规则(例如 strictNullChecks: false)。在生产项目中,强烈建议将 "strict": true 开启以捕获潜在的空指针异常。

但在 NestJS 中开启 strict: true 后,开发者经常遇到如下报错:

常见编译错误
Property 'username' has no initializer and is not definitely assigned in the constructor.

这是因为在 DTO(数据传输对象)和 ORM 实体(如 TypeORM / Prisma Entity)中,属性通常是通过 Class-validator 装饰器或数据库驱动在运行时赋值的,并不在 TypeScript 构造函数中直接初始化。针对此场景,推荐以下两种解决方案:

  • 方案 A(推荐):使用明确赋值断言符号 !
    在类属性声明时加上感叹号,例如 username!: string;,既保留了全工程的严格空值检查,又精确告知编译器该属性将由框架运行时注入赋值。
  • 方案 B:在 tsconfig 中单独关闭属性初始化检查
    若遗留代码量过大,可在 compilerOptions 中保留 "strict": true 的同时,显式设置 "strictPropertyInitialization": false。

3. 配置路径别名(Path Mapping)

随着业务模块增加,深层相对路径(如 import { UserService } from '../../../services/user.service')极易出错且不易重构。在 tsconfig.json 中配置路径别名可以彻底解决该问题:

{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"],
      "@common/*": ["src/common/*"]
    }
  }
}

配置完成后,即可在任何文件中采用简洁的 import { UserService } from '@/services/user.service' 形式导入模块。

易混淆辨析:很多开发者认为只要在 tsconfig.json 中配置了 paths,项目在任何环境下都能正常运行。其实不然!TypeScript 编译器在生成 JavaScript 时不会自动修改 import 路径。在开发阶段,npm run start:dev 之所以能正常工作,是因为 NestJS 内部集成了 tsconfig-paths 工具库在 Node.js 运行时动态映射了别名;但在生产打包后若直接脱离 Nest 运行 node dist/main.js,原生 Node.js 将无法识别 @/ 别名并报错。若需要独立运行编译后的 JS,可在入口引入 tsconfig-paths/register 或配合构建工具转换路径。

4. 推荐的标准 tsconfig.json 配置范本

综合以上原则,一套稳定、严谨的商业级 tsconfig.json 推荐配置如下:

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strict": true,
    "strictPropertyInitialization": false,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

五、开发体验增强与常见问题排障决策

随着业务代码膨胀,默认基于 tsc 的编译耗时会显著上升。NestJS CLI 支持将编译器平滑切换至 SWC(Speedy Web Compiler),大幅缩减启动与热更新耗时。

1. 使用 SWC 加速开发与构建

安装 SWC 核心与 Nest 适配包:

安装命令
npm i -D @swc/cli @swc/core

在启动或构建时追加 -b swc 参数即可启用:

SWC 启动命令
nest start -b swc --watch

SWC 采用 Rust 编写,编译速度比原生 tsc 快一个数量级。需要注意的是,SWC 在转换装饰器时必须确保开启 legacy decorator 模式与类名保留,以避免影响 NestJS 的依赖注入识别。

2. 开发环境常见故障诊断树

当遇到编译失败或环境配置异常时,可根据下方决策树进行针对性排查:

怎么使用 NestJS CLI 初始化项目并配置 TypeScript 开发环境
图 4:NestJS TypeScript 开发环境常见异常定位与解决决策树
故障现象 根本原因 修复动作
依赖无法解析
Nest can't resolve dependencies
tsconfig.json 未开启元数据发射,或者服务类漏加 @Injectable() 装饰器。 确认开启 emitDecoratorMetadata: true 与 experimentalDecorators: true,并在对应类上方添加装饰器。
路径别名报错
Cannot find module '@/...'
配置了 paths 但未设置 "baseUrl": "./",或路径映射相对根目录错误。 检查 tsconfig.json 确保 baseUrl 存在,且 paths 中的路径通配符与目录真实结构一一对应。
热更新失效或 CPU 占用过高 dist 产物或临时缓存未被忽略,导致监听器进入死循环。 确认 nest-cli.json 开启了 deleteOutDir: true,并在 .gitignore 中排除了 dist。
构建产物过大
包含 *.spec.js
使用了原生 tsc 构建,忽略了 tsconfig.build.json 的排除规则。 使用 nest build 执行构建,或在脚本中显式指定 tsc -p tsconfig.build.json。

六、配置清单与落地总结

初始化 NestJS 项目并搭建稳健的 TypeScript 开发环境,本质上是脚手架工具链与类型系统规则的高效协同。落地时遵循以下四条核心准则:

  1. 创建阶段:优先使用 npx @nestjs/cli new 保证脚手架独立性,合理选用高效包管理器。
  2. 配置阶段:严格保留 emitDecoratorMetadata 与 experimentalDecorators 这两根框架基石,根据团队规范开启 strict 模式并使用断言符号管理实体属性。
  3. 构建阶段:明确划分 tsconfig.json(面向 IDE 与单测)和 tsconfig.build.json(面向纯净生产包)的双层边界,防止测试文件渗入生产发布镜像。
  4. 运行阶段:大型项目中善用 SWC 构建加速器与路径别名,提升日常编码反馈效率。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章