侧边栏壁纸
博主头像
恪晨博主等级

前端程序员

  • 累计撰写 144 篇文章
  • 累计创建 41 个标签
  • 累计收到 17 条评论

目 录CONTENT

文章目录

Umi4+Nestjs+Vercel开发与部署

恪晨
2023-03-02 / 0 评论 / 3 点赞 / 245 阅读 / 1,533 字 / 正在检测是否收录...

前言

  在很久之前写过在Vercel上部署Nestjs项目,实现node服务的访问,最近整理了一个完整的前后端项目,实现了对接mysql数据库以及基本的curd功能,并且部署在了vercel上,由于vercel的每一个服务的域名时不同的,并且不能设置多个项目不能设置同一个域名,因此需要在前端访问时最请求接口进行代理访问,代理访问的配置方式也在之前的一片文章专门写过。

服务端开发

  通过使用nestjs脚手架进行项目初始化,然后实现相关的代码开发,采用了的express平台。

  • 初始化项目
    使用脚手架命令 nest new myapp进行项目初始化;
  • 安装所需依赖
    npm install -S @nestjs/config @nestjs/swagger @nestjs/typeorm class-transformer class-validator dayjs mysql2 typeorm yaml
    
  • 配置swagger
    • 在main.ts中引入swagger,配置以下内容,配置完成后可通过http://localhost:3000/swagger/访问即可
      import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
      
      ......
      
      const config = new DocumentBuilder()
      .setTitle('Server Application')
      .setDescription('Server API Application')
      .setVersion('v1')
      .addTag('')
      .build();
      
      const document = SwaggerModule.createDocument(app, config);
      SwaggerModule.setup('swagger', app, document);
      
      console.log('Application Swagger is running on: http://localhost:3000/swagger/');
      
  • 新增一个模块
    通过使用nestjs内置的命令快速生成一个模块,如下表示快速生成一个user模块,并且将这个模块放置在modules文件夹下同时不生成测试文件,通过这个命令生成user模块后,会自动注入到App.module中,同时可选择使用哪一类规范的接口,默认为restful
    nest g resource modules/user --no-spec
  • 配置连接数据库
    • 在之前已经安装好了相关的依赖,使用了mysql数据库,我们在根目录新建一个config文件夹,在下面新建一个config.yml文件,设置数据库相关的信息
    MYSQL_CONFIG:
        name: "test" # 自定义次数据库链接名称
        host: 127.0.0.1
        port: 3306
        username: "root"   # 数据库链接用户名
        password: "12345"     # 数据库链接密码
        database: "test"      # 数据库名
        logging: false       # 数据库打印日志
        synchronize: true 
    
    • 在根目录下新建一个utils文件夹,下面新建一个index.ts文件,主要内容如下,主要用于读取数据库配置信息

      import * as fs from 'fs';
      import * as path from 'path';
      import * as process from 'process';
      import { parse } from 'yaml';
      export const getConfig = () => {
        const yamlPath = path.join(process.cwd(), `./config/config.yaml`);
        const file = fs.readFileSync(yamlPath, 'utf-8');
        return parse(file);
      };
      
    • 在src的modules文件夹下新建一个database模块用于初始化数据库配置,并且将这个模块进行exports,主要需要两个文件database.module.tsdatabase.prodiver.ts,这里我们其实是自定义了一个Provider

      • database.module.ts
        import { Module } from '@nestjs/common';
        import { DatabaseProviders } from './database.provider';
        
        @Module({
          providers: [...DatabaseProviders],
          exports: [...DatabaseProviders],
        })
        export class DatabaseModule {}
      
      • database.prodiver.ts
        import { DataSource, DataSourceOptions } from 'typeorm';
        import { getConfig } from '../../utils';
        import * as path from 'path';
        // 设置数据库类型
        const databaseType: DataSourceOptions['type'] = 'mysql';
        const { MYSQL_CONFIG } = getConfig();
        
        const MYSQL_DATABASE_CONFIG = {
            ...MYSQL_CONFIG,
            type: databaseType,
            // 必须配置
            entities: [path.join(__dirname, `../../**/*.entity{.ts,.js}`)],
        };
        
        const MYSQL_DATA_SOURCE = new DataSource(MYSQL_DATABASE_CONFIG);
        
        // 数据库配置导出
        export const DatabaseProviders = [
            {
                provide: 'MYSQL_DATA_SOURCE',
                useFactory: async () => {
                    await MYSQL_DATA_SOURCE.initialize();
                    return MYSQL_DATA_SOURCE;
                }
            },
        ];
      
    • 在app.module中引入数据库配置

    import { ConfigModule } from '@nestjs/config';
    import { DatabaseModule } from '@/modules/database/database.module';
    import { getConfig } from './utils/index';
    
    @Module({
        imports: [
          ConfigModule.forRoot({
            // 开启全局配置
            ignoreEnvFile: true,
            isGlobal: true,
            load: [getConfig],
          }),
          DatabaseModule,
          UserModule,
        ],
        controllers: [AppController],
        providers: [AppService],
      })
    
  • 在User模块中使用数据库
    • 首先在User模块下新建一个user.provider.ts文件,用于引入数据库配置
     import { User } from './entities/User.entity';
     export const UserProviders = [
       {
         provide: 'USER_REPOSITORY',
         useFactory: async (AppDataSource) => await AppDataSource.getRepository(User),
         inject: ['MYSQL_DATA_SOURCE'],
       },
     ];
    
    • 在User.module中引入userProvider,同时也要引入DatabaseModule
      import { DatabaseModule } from '@/modules/database/database.module';
      import { UserProviders } from './user.providers';
      @Module({
        imports: [DatabaseModule],
        controllers: [UserController],
        providers: [UserService, ...UserProviders],
      })
    
    • 在User.service中注入USER_REPOSITORY进行使用
      import { Injectable, Inject } from '@nestjs/common';
      import { CreateDiaryDto } from './dto/create-user.dto';
      import { Repository } from 'typeorm';
      import { User } from './entities/user.entity';
      
      @Injectable()
      export class UserService {
        constructor(
          @Inject('USER_REPOSITORY')
          private userRepository: Repository<User>,
        ) {}
        
        // 增加
        create(createUserDto: CreateUserDto) {
          return this.userRepository.save(createUserDto);
        }
      }
    
      通过以上配置,在User模块中我们就能正常的连接数据库进行数据操作了,当新增相关的模块的时候,也是使用这种方式即可。
  • 配置相关的过滤器、异常处理器
    可根据实际需要配置相关的异常处理,统一的返回数据格式处理等,这里就不再赘述

部署

  项目部署我们依旧是采用了Github的Action进行自动化部署,只需push代码后自动构建部署,具体请参考:部署

移动端开发

  移动端采用了alitajs生成移动端项目,可根据官方文档进行生成,与Umi使用方式基本类似,同时已经集成了antd-mobile5,根据实际业务开发即可。

部署

  在开头我们提到过由于vercel的原因,我们需要配置接口代理,因此在前端项目中,我们需要设置一个vercel.json的文件,将前端访问后端的接口代理到后端的地址,内容如下,将接口/api下所有的请求都代理到https://server.vercel.app服务上,直接提交代码后就可以自动部署啦,部署好以后就可以直接访问了

{
    "version": 2,
    "routes": [
        {"src": "/api/.*","dest": "https://server.vercel.app"}
    ]
}

总结

  通过以上内容,我们就实现了使用Umi+Nestjs+vercel部署前后端项目了,当然后端的数据库是需要自己的,毕竟vercel不会提供存储服务。

3

评论区