pm2 + ts-node 的那些坑

注意事项

Ecosystem File 按照如下写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const fs = require("fs");

let interpreter;
if (process.platform === "win32") {
interpreter = "/.bin/ts-node.cmd";
} else {
interpreter = "./node_modules/.bin/ts-node";
}


module.exports = {
apps: [{
name: 'my-app',
interpreter,
interpreter_args: '-r tsconfig-paths/register',
instance_var: 'INSTANCE_ID',
instances: 6,
exec_mode: 'cluster',
cwd: './',
script: './src/main.ts',
}]}
  1. interpreter 设定为 ts-node 的绝对路径(或相对于配置文件的相对路径),一定不能直接写 ts-node,另外还需要注意 windows 下需要使用 ts-node.cmd
  2. interpreter_args 设定为 -r tsconfig-paths/register
  3. cwd 填写工作目录
  4. script 填写脚本的目标
  5. ts-node 和 typescript 必须同时进行全局安装和项目安装

原因

我们要执行的脚本是 xxx.ts ,pm2 在检测到结尾是 ts 时会直接「明白」应当使用 ts-node。而无论是我们省略 interpreter 还是在 interpreter 下选用 ts-node 都会造成 pm2 使用一个并不存在的路径:pm2 安装目录下的 node_modules 下的 ts-node,而不会使用我们全局或项目中的 ts-node。

1
Error: Interpreter /usr/local/share/.config/yarn/global/node_modules/pm2/node_modules/.bin/ts-node is NOT AVAILABLE in PATH. (type 'which /usr/local/share/.config/yarn/global/node_modules/pm2/node_modules/.bin/ts-node' to double check.)

Unitech/pm2

ts-node 和 typescript 必须进行项目安装的原因便是因为我们必须给定一个指向了 ts-node 的绝对路径(或相对路径),才能不触发 pm2 的在其自己的 node_modules 目录下寻找 ts-node 的逻辑。

而必须也在全局安装(其实并不是,主要是需要和 pm2 在同一环境下安装,如果你的 pm2 本身就没有全局安装那么可以忽略这个)的原因是 pm2 另一个「智能」的解决方案:检测到后缀名是 .ts.tsx 会直接帮我们 require("ts-node/register") 。。。。

Unitech/pm2

TIPS

  1. pm2 install 就是个残废品,真的不想把 ts-node 和 typescript 装两次就做软链吧
  2. 其实还有一个方式就是专门写一个 run.js 的文件,在这里再进行 ts 代码的引入执行等,入口文件不以 ts 结尾就不会触发 pm2 的各种奇奇怪怪逻辑(重点是还没文档……)