安装环境
要做Node.js编程嘛,Node.js是必须安装的,大家可以到官网(https://nodejs.org)下载安装,推荐安装LTS版本。
安装完Node.js后,打开你系统的命令行,输入下面的命令确认安装是否成功:
代码语言:javascript复制node -v
#命令行输出例如 v12.13.0 这样的版本号信息,则说明安装已经成功
接着,我们需要开始安装NestJS框架的命令行工具了,它可以帮助我们在开发的过程中生成骨架代码等,比较方便。我们继续在命令行上执行如下命令开始安装:
代码语言:javascript复制#使用Node.js自带的npm安装:
npm i -g @nestjs/cli
#如果你使用的是yarn,则可以执行如下命令来安装:
yarn global add @nestjs/cli
安装完成后,在命令行继续输入下面的命令来验证安装是否成功:
代码语言:javascript复制nest -V
#输出版本号信息,则说明安装已经成功
以上这些就是必备的环境安装了,其他的例如代码编辑器软件之类的辅助开发工具,可以根据自己的喜好来选择。当然,代码编辑器,我们首推Visual Studio Code(https://code.visualstudio.com/),前端开发者都爱用!而且它对TypeScript的支持是太棒了(没办法,亲儿子能不棒吗)。
起手式:生成新项目
我们可以通过之前安装好的NestJS命令行工具,来创建我们的第一个NestJS项目:
代码语言:javascript复制nest new myserver
#执行过程中会让你选择使用 npm 还是 yarn 作为包管理工具,
#请按照你的实际情况来选择,不知道的话直接选择 npm 就行了
看到如下的信息,就表示已经生成成功了。有钱有爱心的朋友们可以给他们小小的捐献一下,支持一下NestJS这么好的项目:
然后呢,我们可以尝试把这个新项目运行起来,看看效果如何:
代码语言:javascript复制cd myserver
npm run start
#或者 yarn run start
这样就能将这个NestJS生成的服务端程序运行起来了,它默认监听在3000端口。我们可以在浏览器里输入如下的地址访问:http://localhost:3000/
是不是看到了一个既朴素又雅致,让人感到亲切又兴奋激动,好似来自远方的朋友的热情问候:Hello World!
项目源代码
使用代码编辑器打开这个新项目,我们可以看到主要有4个目录:
- node_modules - Node.js项目的依赖模块目录
- src - 存放业务代码以及单元测试代码的目录
- test - 存放端到端(e2e)测试代码的目录
- dist - TypeScript代码最终都会被编译成JS代码执行,这个就是存放最终编译后的代码的目录
其中src应该是我们最关心的目录,我们大部分的功能实现代码都将会从这里开始。这个新项目骨架中提供的代码是非常简单的:
- main.ts 是主入口文件
- app.module.ts、app.controller.ts、app.service.ts 组成了一个业务模块
- app.controller.spec.ts 是 app.controller.ts 的单元测试
我们先来看一下业务代码模块的3个代码文件:
首先是 app.service.ts,这个文件命名遵循了一定的规范,在文件名中加入了一个 .service 的后缀,代表它里面包含的是一些业务逻辑。虽然这个命名不是强制的,但是遵循这样的规范有助有组织我们的代码文件,在项目文件多了以后,方便查找。
代码语言:javascript复制import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
在这段代码中,实现了一个非常简单和普通的AppService类,这个类中只有一个业务方法 getHello(),它返回一个字符串。但是在这个类上,使用了一个我们在JavaScript里没见过的东西 @Injectable,这个东西叫做装饰器(Decorator),熟悉Java的朋友一定会觉得这个装饰器和Java里面的注解(Annotation)非常像,的确,其实功能也类似。如果你了解Java的Spring框架,那理解起来就更无障碍了。
关于装饰器的具体内容,我们后面专门在讲解TypeScript特性的时候再详细讲。这里出现的 @Injectable 装饰器,你可以简单的理解为当前这个 AppService类将会被创建一个对象实例,然后扔到一个池子中,等待被使用。
看完 app.service.ts,再来看 app.controller.ts,同样有类似的文件命名规则,来表明它是一个请求控制器角色,可以处理接收到的REST API 请求:
代码语言:javascript复制import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
在这个控制器的代码中,我们看到了更多的装饰器:@Controller 作用于AppController类上,@Get 作用于类方法getHello()上。这两个装饰器非常重要,它们决定了HTTP请求的路由路径会被具体映射到哪个类、哪个方法上去执行。这两个装饰器也可以传入参数,比如改为 @Controller('myapp') 、@Get('greeting')后,访问之前的URL路径将产生错误,而访问新的路径则能得到正常的信息:http://localhost:3000/myapp/greeting
大家可以尝试修改自己的代码,来体会一下它的作用。另外,我们看到在 AppController 类中使用到了之前的 AppService 类,并调用了它的实例 appService.getHello() 方法。实例对象 appService 在 AppController 的构造函数参数中被声明,但是我们其实并没有看到它被实例化,未实例化的对象是不能调用它上面的方法的,那这是怎么回事?其实这就是整个NestJS框架的核心功能:依赖注入 这只无形的手在发生作用。还记得前面那个说被扔到池子里去的AppService类的实例对象么?它在此时被从池子里捞了出来,组装进了AppController中。
然后是 app.module.ts,这个文件很简单,没有什么逻辑,只是声明了一个空的AppModule类,并用 @Module 装饰器对另外2个文件进行了配置:app.controller.ts 中的 AppController 是属于 controllers,会被当做请求控制器来进行处理;而 app.service.ts 中的 AppService类是归为 providers,将被当做通用服务提供者进行处理。
代码语言:javascript复制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 装饰器配置过的内容,你可以想象成一个逻辑上被独立打包在一起的模块。在实际的应用开发中的应用场景可能是这样的:你的软件可能会有“用户管理”和“产品管理”等不同的业务功能,这种情况下,就可以将它们组织在不同的 Module 模块中管理。
业务模块代码看完了,最后我们来看一下程序的入口代码 main.ts:
代码语言:javascript复制import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
入口代码中,使用 NestFactory.create() 创建了一个基于 AppModule 这个模块的Nest应用实例,并开启 3000 端口,接受外界的请求。
总结
以上就是从环境安装到生成第一个NestJS项目的简要介绍,如果你也动手做过了,我相信你肯定已经收获了比本文讲的多得多的东西。在后续的文章和视频中,我们将一点一点展开,深入讲解NestJS和TypeScript相关的各种知识。