前言
Nestjs和Prisma的打包部署教程很少,网上比较热门的一个就是利用webpack将Nestjs打包 ,它和前端的打包差不多,会把所有的依赖项打包进来,生成的dist目录,可以直接单独部署,而如果我们使用Nestjs提供的build命令打包,不改动它的情况下,它只会将开发目录中的ts文件,转换成js文件,丢入dist目录中,其他什么也不做,就是个ts转js。
这估计会让大部分人诧异,如果遵循官方这种方式,你在启动node服务的时候就必须使用dist目录下的main.js文件了。但是还要考虑环境变量等文件,我们下面细说。
Prisma的打包部署需要考虑两方面:一是需要同步数据库模型,也就是如何使用开发时生成的迁移文件?二是需要生成后端服务使用的client客户端代码。
本次教程也不会搞那么复杂,就是传统的node服务部署,不会使用webpack打包特殊处理,你有兴趣可以自己百度搜索对应关键词就行。
部署代码
虽然nestjs会生成dist目录,但是我们并不能直接使用它,其实还是和koa,express部署差不多,我们需要将开发的代码都丢入生产环境中,虽然有点强迫症,觉得没必要把开发的文件都上传,但是为了方便,这样做是目前最优解,我们通过git仓库将开发代码上传,然后在生产环境git拉取。
可以通过环境变量来做一个简单的环境区分,我们开发的代码不会上传.env.production
文件,这个文件需要生产环境自己创建。
比如我们现在创建一个.env.production文件
# 模式
NODE_ENV="production"
# prisma
DATABASE_URL="mysql://xxx:xxx@localhost:3306/nest-blog"
# hash-saltOrRounds
HASH_SALT_OR_ROUNDS="12"
# token-secret
TOKEN_SECRET="xxxxx"
# upload-path
UPLOAD_PATH="uploads"
现在我们生产环境所需要的文件都有了,就开始安装依赖:
pnpm i
Nestjs 打包
我们在创建Nestjs项目的时候,官方预设了一个build
命令。
package.json
{
"scripts": {
"build": "nest build"
}
}
这个命令会生成dist目录,里面是ts转js后的文件。
然后官方其实还预设了一些start
命令用于启动服务。
{
"scripts": {
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main"
}
}
nest start
命令是通过 CLI 工具启动应用程序的标准方式,它会根据nest-cli.json
和tsconfig.json
配置,来运行src/main.ts
文件。
所以前三个命令其实都是用于开发用的。
其中start
用于单次启动服务,临时服务之类的。
start:dev
则是开发使用,它加入了watch用于动态更新。
start:debug
则是加入了debug的dev模式。
第四个start:prod
则是用于启动生产环境下的应用程序,所以他是通过node
启动的dist目录下main文件。
但是,这个命令有点不对,因为现在的nest打包后,dist目录下存在一个src目录,在src目录下才会有main.js文件,所以我们需要改动一下。
{
"scripts": {
"start:prod": "node dist/src/main"
}
}
第二个问题是,node启动服务,如果指定NODE_ENV
,那么通过process.env.NODE_ENV
得到的就是一个undefined,这显然是不行的,因为之前我们的ConfigModule中就用到了它,所以我们还需要显式指定,为此我们需要一个依赖cross-env。
这个之前应该已经安装了,没有的话自己按一下:
pnpm i cross-env
然后命令调整:
{
"scripts": {
"start": "cross-env NODE_ENV=development nest start",
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:debug": "cross-env NODE_ENV=development nest start --debug --watch",
"start:prod": "cross-env NODE_ENV=production node dist/src/main"
}
}
简单的启动命令就完事,如果需要使用PM2来实现持久化,我推荐是使用宝塔面板来帮助我们操作,或者你自己安装PM2,然后在项目根目录配置一个ecosystem.config.js
文件,内容示例:
module.exports = {
apps : [{
name: 'my-nest-app', // 应用程序的名称
script: 'dist/src/main.js', // 应用程序的启动脚本
instances: 'max', // 启动尽可能多的实例
exec_mode: 'cluster', // 启动集群模式
env: {
NODE_ENV: 'production' // 环境变量
}
}]
};
然后用PM2启动这个文件:
pm2 start ecosystem.config.js
不想配文件可以使用如下命令:
pm2 start node --name "my-nest-app" -- NODE_ENV=production -- dist/src/main.js
也是可以的。
但是如果使用宝塔,可视化相对来说对于非专业运维,确实减少了不少麻烦。
可视化配置一下省事很多,还能直接配置域名相关处理。
到这里就完事了,但是还不能直接启动,因为prisma还没弄呢。
Prisma部署
nestjs的build打包跟prisma其实没啥太大关系,所以不要关心dist目录下的prisma,那个完全用不到。
首先我们要保证项目根目录是有prisma目录的,这个目录是prisma自己init的时候生成的,然后我们在调整表结构模型schema.prisma
文件之后,都会运行prisma migrate dev
生成迁移文件,这个非常重要,一定要有迁移文件。
在这之前,我贴一下package.json中我配置的几个快捷命令:
{
"scripts": {
"prisma:migrate": "dotenv -e .env.development prisma migrate dev",
"prisma:reset": "dotenv -e .env.development prisma migrate reset",
"prisma:deploy": "dotenv -e .env.production prisma migrate deploy",
"prisma:generate": "dotenv -e .env.production prisma generate"
}
}
这里用到了dotenv
依赖,没有的话自己安装一下。
pnpn i dotenv
我通过dotenv 指定了环境变量文件,其中prisma:deploy
和prisma:generate
是用于生产环境,deploy命令会基于迁移文件去同步数据库,比如字段更新,创建数据库之类的。
然后generate
生成@prisma/client
依赖于node_modules目录下。
所以每次部署更新,都需要运行这两个命令。
这样之后我们才可以去运行Nestjs项目,才不会爆prisma相关的错误。
我们在运行deploy
命令时可能会遇到一个异常,大概率是权限不足的问题,可以通过chmod +x
的形式。
比如我就碰到了如下报错:
dotenv -e .env.production prisma migrate deploy
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": MySQL database "nest-blog" at "localhost:3306"
Error: Schema engine exited. Error: Command failed with EACCES: /www/wwwroot/www.kod.com/nest-blog/node_modules/.pnpm/@prisma+engines@5.8.0/node_modules/@prisma/engines/schema-engine-debian-openssl-3.0.x cli --datasource <REDACTED> can-connect-to-database
spawn /www/wwwroot/www.kod.com/nest-blog/node_modules/.pnpm/@prisma+engines@5.8.0/node_modules/@prisma/engines/schema-engine-debian-openssl-3.0.x EACCES
ELIFECYCLE Command failed with exit code 1.
然后我通过运行:
chmod +x /www/wwwroot/www.kod.com/nest-blog/node_modules/.pnpm/@prisma+engines@5.8.0/node_modules/@prisma/engines/schema-engine-debian-openssl-3.0.x
将对应文件提权,然后在运行deploy
就行了。
简化命令
每次部署的时候,都需要先build打包,打包后运行prisma的deploy
和generate
才可以运行后端服务,每次都输好几次命令,非常麻烦,我们可以进行简化处理。
安装一个合并命令依赖:
pnpm i npm-run-all2 -D
配置如下:
package.json
{
"scripts": {
"build": "nest build",
"prisma:deploy": "dotenv -e .env.production prisma migrate deploy",
"prisma:generate": "dotenv -e .env.production prisma generate",
"build:prod": "run-s build prisma:deploy prisma:generate"
},
}
创建了build:prod
命令,这个名字可以自己取,然后通过run-s
顺序运行对应的命令即可。
之后每次项目更新,直接运行build:prod
就可以一键完成打包,同步数据库模型,生成新的prisma客户端。
📮评论