在学校时逛某大佬的博客,就想过也搞个自己的网站。刚毕业那会服务器便宜,一年才一百多,在那时还注册了域名。谁知第一家公司加班太严重没时间维护,服务器到期后费用也贵了就没续期。
后面换公司后工作轻松多了,躺平了亿段时间后,萌生了使用Nestjs再搞个个人网站的想法!
同时还想搞个自己的动态接口系统(创建不同配置,每个配置动态创建对应的表,接口查询逻辑一致,根据配置不同有动态的查询参数,根据配置id请求不同的表),以后搞项目所需的接口也更方便了。
这是一个系列文章,如果有感兴趣的小伙伴,可以跟着过一遍,相信应该会有所收获。技术有限,如有不对的地方大佬们多多包涵,欢迎指点。 在技术方面,暂计划后端用nestjs + myql,前端使用vue 全家桶!
Nestjs初识
nestjs中文文档介绍
- Nest 是一个用于构建高效,可扩展的 Node.js 服务器端应用程序的框架。它使用渐进式 JavaScript,内置并完全支持 TypeScript(但仍然允许开发人员使用纯 JavaScript 编写代码)并结合了 OOP(面向对象编程),FP(函数式编程)和 FRP(函数式响应编程)的元素。
- 在底层,Nest使用强大的 HTTP Server 框架,如 Express(默认)和 Fastify。Nest 在这些框架之上提供了一定程度的抽象,同时也将其 API 直接暴露给开发人员。这样可以轻松使用每个平台的无数第三方模块。
用个人的话来说就是开发者可以使用TypeScript编写Nest程序,同时也允许开发者使用纯JavaScript编写。 Node.js提供了http模块处理请求响应,但是它的api过于原始,于是乎出现了Express这类库封装了一层方便我们使用Node.js提供的Api。Express本身定位并不是框架(就好像Jquery对原生DOM Api进行封装,方便Api的调用),开发者编写程序比较自由,当模块多了后就不好管理,比如划分项目结构问题等。而Nestjs在底层使用了Express(默认)和Fasyify的基础上提供了一层接口,并能够使用底层特定框架的Api,还同时引入了MVC、IOC解决了架构问题。并在对底层框架平台的整合上利用了适配者模式,使灵活选用底层底层架构。
项目搭建
开发者可以使用Nest CLI搭建项目,也可以直接克隆启动项目
$ npm i -g @nestjs/cli
$ nest new project
执行nest new nest-lw
(这里我的项目名为nest-lw)创建完项目后,会询问使用哪种包管理。
这里我选择使用yarn
做为包管理来安装依赖,安装完成后根据提示启动项目
$ cd nest-lw
$ yarn start
根据提示执行yarn start
启动项目【执行yarn start:dev
可监听文件变化并自动编译,更多命令可看package.json下的scripts】。
此时,Nest的Hello word程序就启动成功了。在浏览器中输入localhost:3000,Nest初始程序默认监听的3000端口,如果3000端口被占用,可在main.js
中修改为其他端口。
初始项目结构
新建的项目结构如图,简单说明
文件 | 说明 |
---|---|
dist | 项目编译后产物 |
node_modules | 安装包目录 |
src | 源代码目录 |
test | 测试文件目录 |
.eslintrc.js | ESLint配置文件 |
.gitignore | git用于配置忽略文件的文件 |
.prettierrc | prettier插件 格式化、美化代码配置 |
nest-cli.json | 项目配置文件 |
package.json | 项目管理(描述)文件 |
README.md | 项目说明文件 |
tsconfig.build.json | TypeScript构建时配置文件 |
tsconfig.json | TypeScript配置文件,配置一些编译器参数 |
yarn.lock | 固定依赖包文件 |
src为源代码目录,是后续逻辑编写的主要文件,后续99.9%工作都是在这个目录下进行。src目录简单说明下
src目录下文件 | 说明 |
---|---|
app.controller.spec.ts | 对于控制器的单元测试用例 |
app.controller.ts | 控制器文件,也是用于配置路由的文件 |
app.module.ts | 模块文件,一般的按模块编写功能,比如用户模块,支付模块 |
app.service.ts | 服务文件,顾名思义就是提供服务的,业务逻辑一般编写在该类文件内 |
main.ts | 项目入口文件,在该文件内引入主模块开始业务逻辑。以及编写全局管道、全局过滤器等,和对端口的修改 |
入口文件
项目的入口文件在src/main.ts
,可以看到里面内容比较简单
import { NestFactory } from '@nestjs/core'; // 导入nest工厂对象
import { AppModule } from './app.module'; // 导入App模块
async function bootstrap() {
const app = await NestFactory.create(AppModule); // 使用工厂方法创建AppModule实例
await app.listen(3000); // 监听端口
}
bootstrap();
入口文件只是使用nestjs
的工厂函数创建了个AppModule
实例,然后监听了3000端口,我们也可以在这修改端口号。
模块(Module)
在nestjs
中都是按模块划分的,比如入口文件导入的根模块AppModule
,文件在src/app.module.ts
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是一个装饰器,用来定义一个模块,初始化的AppModule模块只使用了3个属性。实际@Module支持接收4个属性:
imports
: 导入服务,需要使用的其他模块的服务,在这导入controllers
: 导入控制器,处理请求,控制路由,调用providers服务providers
: 导入提供者,处理具体的业务逻辑exports
: 导出服务,如果希望模块下的服务能够被其他模块使用,需要在这里导出
控制器(Controller)
跟随AppModule
找到AppController
文件在src/app.controller.ts
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
在constructor中使用AppService定义了appService(相当于 this.appService = new AppService()
)。并且使用@Get()
装饰器定义了一个get请求方法getHello,然后该方法调用了appServecie.getHello方法。我们先来看下这个AppService
,在src/app.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
可以看到AppService
服务就是使用@Injectale()
装饰的一个类,也叫提供者(Providers)。AppService
定义了getHello
方法,该方法返回了个字符串Hello World!
,也就是前面浏览器地址localhost:3000
的输出结果。
nestjs
处理请求大致是根据cgi匹配到模块引入的控制器中对应的方法
提供者(Providers)
使用@Injectale()
装饰的类都可以叫做提供者(Providers),比如上面提到的服务(Service)。许多基本的 Nest
类可能被视为 provider - service
, repository
, factory
, helper
等等。
在Module中注入了提供者,就能在Controller中使用。比如上面AppModule中注入了AppService,在AppController中就能使用。该种注入Service写法是一种简写方式,而注入提供者有多种形式。
@Module({
// ...
providers: [
// 1 直接导入一个服务提供者,简写。完整写法如下2
AppService,
// 2 useClass
{
provide: AppService,
useClass: AppService
},
// 3 useValue 注入值
{
// provide是一个字符串,使用时需添加@Inject('providez值'),
// 比如 constructor( @Inject('infos') private readonly infos ) {}
provide: "infos",
useValue: { env: 'test' }, // 需要注册的值,比如对象,数组..
},
// 4 useFactory 当依赖其他提供者,可使用useFactory, 并通过inject注入依赖
{
provide: "user",
inject: [AuthService], // 注入需要的依赖
useFactory(AuthService: AuthService) {
return new UserService(AuthService)
}
},
// 5 当需要异步操作时
{
provide: 'ASYNC_CONNECTION',
useFactory: async () => {
const connection = await createConnection(options);
return connection;
},
}
]
})
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。
在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。
本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。
除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。
在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!