使用pm2部署koa+ts项目产生的问题
项目背景:
- 使用Koa+ts装饰器模式
- pm2执行命令:
"start": "export NODE_ENV=prod&& pm2 start --interpreter ./node_modules/.bin/ts-node ./src/app.ts --name app -i 2 --watch"
- 服务器CentOS7.4版本,安装node16.17.0版本
- 我的tsconfig.json文件如下
{ "compilerOptions": { "target": "ES5", "useDefineForClassFields": false, "module": "CommonJS", "rootDir": "./src", "outDir": "./tsbuild", "moduleResolution": "Node", "allowJs": true, "strict": true, "sourceMap": true, "baseUrl": ".", "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "lib": ["ESNext", "DOM"], "skipLibCheck": true, "noEmit": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "paths": { "@/*": ["src/*"] } }, "include": ["src/**/*.ts", "src/**/*.d.ts"] }
问题1:在执行npm run start
的时候,会一直报一个Error:(21, 3) TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning.
分析1:自己项目的根目录tsconfig.json确实有设置experimentalDecorators,但是问题就在于未生效,可是经过测试,在tsconfig.json修改部分属性是可以生效的,导致我误以为tsconfig.json是生效的,这也是我疑惑的点,可是经过测试就是ts-node在运行的时候没有读取到我们的tsconfig.json的配置,难道是默认使用tsconfig.json和我们的tsconfig.json有个默认合并规则吗,这里我的实力还无法验证。
解决1:得想个办法让pm2在运行ts-node使用到我们根目录的tsconfig.json配置文件,这里原始的pm2.config.js配置文件为
module.exports = {
apps: [
{
name: 'app',
script: 'src/app.ts',
watch: true,
ignore_watch: ['logs', 'node_modules'],
out_file: 'logs/out/out.log',
error_file: 'logs/error/error.log',
interpreter: './node_modules/.bin/ts-node',
interpreter_args: '-P ./server -r tsconfig-paths/register',
instances: 1,
autorestart: true,
exec_mode: 'cluster',
env: {
NODE_ENV: 'dev', // prod
port: '3000', // 3001
},
},
],
}
执行脚本"pmconf": "pm2 start pm2.config.js",
这里会引出其他问题,比如WARNING: TO LOAD AN ES MODULE, SET “TYPE“: “MODULE“ IN THE PACKAGE.JSON OR USE THE .MJS EXTENSION.
,然后会引出其他问题,然后继续深入又是修改tsconfig.json和package.json的数据,最后还是无法解决问题,这里修改更正一个有效的pm2.config.js配置文件,使用script属性和args属性代替interpreter和interpreter_args属性,同时需要自行安装一下npm i tsconfig-paths
这个库
module.exports = {
apps: [
{
name: 'app',
// script: 'src/app.ts',
watch: true,
ignore_watch: ['logs', 'node_modules'],
out_file: 'logs/out/out.log',
error_file: 'logs/error/error.log',
// interpreter: './node_modules/.bin/ts-node',
script: './node_modules/.bin/ts-node',
args: '-T -r tsconfig-paths/register ./src/app.ts',
instances: 1,
autorestart: true,
exec_mode: 'cluster',
env: {
NODE_ENV: 'dev', // prod
port: '3000', // 3001
},
},
],
}
最后装饰器的问题都解决了,参考配置如下
"pmconf": "pm2 start ecosystem.config.js",
// pm2.config.js
module.exports = {
apps: [
{
name: 'app',
// script: 'src/app.ts',
watch: true,
ignore_watch: ['logs', 'node_modules'],
out_file: 'logs/out/out.log',
error_file: 'logs/error/error.log',
// interpreter: './node_modules/.bin/ts-node',
script: './node_modules/.bin/ts-node',
args: '-T -r tsconfig-paths/register ./src/app.ts',
instances: 1,
autorestart: true,
exec_mode: 'cluster',
env: {
NODE_ENV: 'dev', // prod
port: '3000', // 3001
},
},
],
}
// tsconfig.json
{
"compilerOptions": {
"target": "ES5",
"useDefineForClassFields": false,
"module": "CommonJS",
"rootDir": "./src",
"outDir": "./tsbuild",
"moduleResolution": "Node",
"allowJs": true,
"strict": true,
"sourceMap": true,
"baseUrl": ".",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts"]
}
自己补充的一个类装饰器的点
export function Controller(modulePath: string = '/') {
console.log('进入装饰器类')
return function (targetClass: { new (...args: any): any }) {
// 使用下面的方式获取请求上的方法名时,Object.keys(targetClass.prototype)获取的值是[],导致我们的Controller的方法压根没有注册到路由中去
Object.keys(targetClass.prototype).forEach((methodName) => {
})
// 使用下面的方式获取的才是Controller中的各种方法组成的数组
Object.keys(Object.getOwnPropertyDescriptors(targetClass.prototype)).filter(
(item) => item !== 'constructor'
)
}
}