万事开头难, 一旦熟练即成老司机, 学习新东西更是如此. 很多东西看着很难, 但是当你真正投入心思进去学习, 去思考, 并真正经过多次的动手实践以后, 你会发现其实也没什么难的. 实践这一条, 对学习编程尤其重要, 你写过代码和只看过书籍或文章对它的感受是完全不一样的, 你在编写, 运行, 调试过程中都会遇到各种各样的问题, 然后你去一点一点的排查解决问题, 经过这一过程建立起非常深刻的印象, 因此对做过的东西的理解程度也会上一个层次.
所以, 下面我们要干什么呢? 对, 操起家伙就是干!
安装环境
要做 Node.JS 编程嘛, Node.JS 是必须安装的, 大家可以到官网 (https://nodejs.org) 下载安装, 推荐安装 LTS 版本.
安装完 Node.JS 后, 打开你系统的命令行, 输入下面的命令确认安装是否成功:
- node -v
- # 命令行输出例如 v12.13.0 这样的版本号信息, 则说明安装已经成功
接着, 我们需要开始安装 NestJS 框架的命令行工具了, 它可以帮助我们在开发的过程中生成骨架代码等, 比较方便. 我们继续在命令行上执行如下命令开始安装:
- # 使用 Node.JS 自带的 NPM 安装:
- NPM i -g @nestjs/cli
- # 如果你使用的是 yarn, 则可以执行如下命令来安装:
- yarn global add @nestjs/cli
安装完成后, 在命令行继续输入下面的命令来验证安装是否成功:
- nest -V
- # 输出版本号信息, 则说明安装已经成功
以上这些就是必备的环境安装了, 其他的例如代码编辑器软件之类的辅助开发工具, 可以根据自己的喜好来选择. 当然, 代码编辑器, 我们首推 Visual Studio Code(https://code.visualstudio.com/), 前端开发者都爱用! 而且它对 TypeScript 的支持是太棒了(没办法, 亲儿子能不棒吗).
起手式: 生成新项目
我们可以通过之前安装好的 NestJS 命令行工具, 来创建我们的第一个 NestJS 项目:
- nest new myserver
- # 执行过程中会让你选择使用 NPM 还是 yarn 作为包管理工具,
- # 请按照你的实际情况来选择, 不知道的话直接选择 NPM 就行了
看到如下的信息, 就表示已经生成成功了. 有钱有爱心的朋友们可以给他们小小的捐献一下, 支持一下 NestJS 这么好的项目:
然后呢, 我们可以尝试把这个新项目运行起来, 看看效果如何:
- 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 的后缀, 代表它里面包含的是一些业务逻辑. 虽然这个命名不是强制的, 但是遵循这样的规范有助有组织我们的代码文件, 在项目文件多了以后, 方便查找.
- 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 请求:
- 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, 将被当做通用服务提供者进行处理.
- 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:
- 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 相关的各种知识.
来源: http://www.jianshu.com/p/82cdd91cc6f1