个人网站记录一 - 前言、初始化Nest

lxf2023-05-14 01:08:36

在学校时逛某大佬的博客,就想过也搞个自己的网站。刚毕业那会服务器便宜,一年才一百多,在那时还注册了域名。谁知第一家公司加班太严重没时间维护,服务器到期后费用也贵了就没续期。

后面换公司后工作轻松多了,躺平了亿段时间后,萌生了使用Nestjs再搞个个人网站的想法!
同时还想搞个自己的动态接口系统(创建不同配置,每个配置动态创建对应的表,接口查询逻辑一致,根据配置不同有动态的查询参数,根据配置id请求不同的表),以后搞项目所需的接口也更方便了。

这是一个系列文章,如果有感兴趣的小伙伴,可以跟着过一遍,相信应该会有所收获。技术有限,如有不对的地方大佬们多多包涵,欢迎指点。 在技术方面,暂计划后端用nestjs + myql,前端使用vue 全家桶!

在正式开始前,会按自己的习惯介绍Nestjs基本使用。有兴趣的可以跟着一起看下,当然推荐大家有空也可以直接逛官方文档

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)创建完项目后,会询问使用哪种包管理。
个人网站记录一 - 前言、初始化Nest

这里我选择使用yarn做为包管理来安装依赖,安装完成后根据提示启动项目 个人网站记录一 - 前言、初始化Nest

$ cd nest-lw
$ yarn start

根据提示执行yarn start启动项目【执行yarn start:dev可监听文件变化并自动编译,更多命令可看package.json下的scripts】。
个人网站记录一 - 前言、初始化Nest

此时,Nest的Hello word程序就启动成功了。在浏览器中输入localhost:3000,Nest初始程序默认监听的3000端口,如果3000端口被占用,可在main.js中修改为其他端口。
个人网站记录一 - 前言、初始化Nest

初始项目结构

个人网站记录一 - 前言、初始化Nest

新建的项目结构如图,简单说明

文件说明
dist项目编译后产物
node_modules安装包目录
src源代码目录
test测试文件目录
.eslintrc.jsESLint配置文件
.gitignoregit用于配置忽略文件的文件
.prettierrcprettier插件 格式化、美化代码配置
nest-cli.json项目配置文件
package.json项目管理(描述)文件
README.md项目说明文件
tsconfig.build.jsonTypeScript构建时配置文件
tsconfig.jsonTypeScript配置文件,配置一些编译器参数
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, repositoryfactoryhelper 等等。

在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为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!