一.前言
既然说要从0~1手搓Nest,那就必然要从最最最基础的工程来写起
大家如果使用过Nest官方提供的CLI成功创建过工程的话,会知道Nest的基础工程目录结构是如下这样子的.
分析一下这几个文件的作用:
- app.module.ts 根模块
- app.controller.ts 控制器
- app.service.ts 服务处理层
- app.controller.spec.ts 测试文件
- main.ts 主文件,用于创建Nest实例并启动Nest应用
理解了初始化文件的作用,下面就对比着源代码来一比一的来搭建自己的Nest应用.
哎先等等,下面就要开始写代码了哦,所以目前您最好先创建一个空工程,并初始化package.json,配置好ts.config,让我们来开始手写Nestjs之旅吧~
示例空目录:
tsconfig.json配置
{
"compilerOptions": {
"experimentalDecorators": true, // 启用装饰器功能
"target": "ES2021",
"module": "CommonJS",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true, // 为运行时提供额外的类型信息(可选)
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"esModuleInterop": true,
}
}
二.分析源码并搭建自己的Nest应用
1. 分析main.ts
- 1.在@nestjs/core核心包中导入NestFactory模块,它用于创建nest应用的实例
- 2.导入App根模块
- 3.定义了一个异步函数(bootstrap),用来创建nest实例并启动应用
- 4.使用NestFactory的静态方法create创建一个nest应用实例,并传入AppModule根模块
- 5.让nest应用实例监听3000端口启动HTTP服务器
- 6.执行bootstrap函数启动Nest应用
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap**();**
通过对main.ts的源码分析,目前可以知道,想要启动Nest服务器起到主要作用的是@nestjs/core包下的NestFactory模块和他暴露出的create/listen这两个静态方法,那么好,现在我们就来实现一个自己的NestFactory模块
写代码之前,必须要清楚的是,Nest.js是依赖express 借鉴angular spring所诞生的nodejs服务端框架,所以express是很重要的,因为Nestjs源码中的NestFactory模块就是依赖的express所编写的.
2.实现自己的NestFactory模块
- 在src目录下新建一个我们自己的@nestjs目录,
- 在@nestjs目录下新建core目录
- 在core目录下新建nestFactory.ts
- 在core目录下新建NestApplication.ts
- 在core目录下新建index.ts
NestApplication(创建Nest应用实例与HTTP服务端口)
NestApplication.ts
// 因为需要使用express构建服务所以需要安装两个依赖: pnpm i express @types/exporess
// 引入express
import express from "express"
// 引入express类型
import type { Express } from "@types/express"
export class NestApplication {
// 将express实例私有化
private readonly app: Express = express()
// protected readonly module等同于 this.module = module
construtor(protected readonly module) {}
// 启动Http服务器
async listen(port: number) {
this.app.listen(port)
}
}
nestFactory.ts
// 引入NestApplication模块
import { NestApplication } from "./NestApplication"
// 创建NestFactory类
export class NestFactory {
// 声明静态方法create,用于创建Nest实例,接收一个模块
static create(module: any) {
// 创建Nest应用实例,这里抽离出另一个类NestApplication,方便维护与扩展
const app = new NestApplication(module)
// 返回Nest应用实例
return app
}
}
3.index.ts
export * from "./nestFactory"
export * from "./nestApplication"
4.实现自己的main.ts
// 引入自己的@nestjs/core中的NestFactory模块
import { NestFactory } from "./@nestjs/core"
// 引入App根模块
import { AppModule } from "./app.module"
// 定义了一个异步函数(bootstrap),用来创建nest实例并启动应用
async const bootstrap = () => {
// 使用NestFactory的静态方法create创建一个nest应用实例,并传入AppModule根模块
const app = await NestFactory.create(AppModule)
// 让nest应用实例监听3000端口启动HTTP服务器
await app.listen(3000)
}
// 执行bootstrap函数启动Nest应用
bootstrap()
--- end NestFactory核心模块完成
三.实现自己的app.controller.ts与手写控制器装饰器
- 在@nestjs目录下新建common目录,用于存放各种装饰器
- 在common目录下新建controller.decorator.ts (控制器装饰器)
- 在common目录下新建index.ts
1. index.ts
export * from "./controller.decorator"
2.实现自己的控制器装饰器 controller.decorator.ts(待完善)
// 需要依赖元数据,所以要安装reflect-metadata: pnpm i reflect-metadata
// 导入元数据包
import "reflect-metadata"
export const Controller = () :ClassDecorator => {
return (target: Function) => {
// todo
}
}
app.controller.ts
import { Controller } from "./@nestjs/common/controller.decorator";
@Controller()
export class AppController {}
四.实现自己的app.module.ts与手写模块装饰器
- 在common目录下新建module.decorator.ts (模块装饰器)
1. index.ts
export * from "./module.decorator"
2.实现自己的模块装饰器 module.decorator.ts(待完善)
// 需要依赖元数据,所以要安装reflect-metadata: pnpm i reflect-metadata
// 导入元数据包
import "reflect-metadata"
// 定义参数类型
interface ModuleMetadata {
controllers: Function[]
}
/**
*
* @param metadata 类的数组
* @returns 类装饰器(模块装饰器)
*/
export const Module = (metadata: ModuleMetadata) :ClassDecorator => {
return (target: Function) => {
// todo
}
}
app.module.ts
import { Module } from "./@nestjs/common/module.decorator"
import { AppController } from "./app.controller"
@Module({
controllers: [AppController]
})
export class AppModule {}
五.运行Nest应用
- package.json添加运行指令, 需要依赖ts-node运行项目
// pnpm i ts-node
"scripts": {
"start": "ts-node src/main.ts",
},
- 访问localhost:3000,如果出现GET NOTFOUND则代表启动成功!
- 完结,下篇文章再见~