前言
在很久之前写过在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/');
- 在main.ts中引入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.ts
与database.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进行使用
通过以上配置,在User模块中我们就能正常的连接数据库进行数据操作了,当新增相关的模块的时候,也是使用这种方式即可。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); } }
- 配置相关的过滤器、异常处理器
可根据实际需要配置相关的异常处理,统一的返回数据格式处理等,这里就不再赘述
部署
项目部署我们依旧是采用了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不会提供存储服务。
评论区