20

I have an application written in Typescript that runs with PM2. Currently I compile to JavaScript, then use PM2 to start the app. My ecosystem.config.js file looks like this:

module.exports = {
  apps: [
    {
      name: 'My Application',
      script: './dist/server/index.js',
      env_qa: {
        PORT: 3001,
        NODE_ENV: 'production',
      },
      env_production: {
        PORT: 3000,
        NODE_ENV: 'production',
      },
    },
  ],
};

I run this with the command:

pm2 stop ecosystem.config.js --env qa

When developing, I just run ts-node server instead of compiling and using PM2. I recently read that ts-node has a 'transpileOnly' or 'fast' mode meaning it can be used in production. Firstly, I'd like to know if it's true that this can be used in production environments. Secondly, how would I still use PM2 to launch my app but using ts-node?

CaribouCode
  • 13,998
  • 28
  • 102
  • 174
  • https://github.com/Unitech/pm2/issues/3503 – baao Jun 12 '19 at 16:23
  • @bambam thanks, I did check that link before I posted the question but was just looking for some clarity. – CaribouCode Jun 12 '19 at 16:25
  • Yeah, doesn't answer the question about fast-mode, but how to run it using ts-node... Thought it might help – baao Jun 12 '19 at 16:26
  • 2
    I am using `pm2 start ts-node -- -P tsconfig.server.json ./server/index.ts` – Sabee Jun 12 '19 at 17:16
  • @Sabee Thanks, and that work as expected for you? Do you notice any performance issues compared to running compiled node code? – CaribouCode Jun 14 '19 at 08:27
  • I'm sorry, but I can't answer this question because I only use it for my hobby project, not for the real world application, but i think it doesn't cause performance issues – Sabee Jun 14 '19 at 18:54

3 Answers3

15

Development Environment

This runtime leads to extremely high memory consumption and server overload, so it should not be used in production.

https://pm2.io/docs/runtime/integration/transpilers/

We don’t recommend using this in production as it slows down your app.

"scripts": {
    "pm2": "NODE_ENV=production pm2 start server.ts --watch"
}

Production Environment

You can transpile TypeScript to JavaScript with a separate command and run it using npm run pm2 (or npm run pm2:staging if you have a staging environment).

The commands npm run prod and npm run staging should only be used locally when you need to work with production and staging environments.

"scripts": {
    "pm2": "NODE_ENV=production pm2 start build/server.js --watch -i max",
    "pm2:staging": "NODE_ENV=staging pm2 start build/server.js --watch -i max",

    "prod": "NODE_ENV=production node build/server.js",
    "staging": "NODE_ENV=staging node build/server.js",

    "dev": "HTTPS=true NODE_ENV=development ts-node-dev --inspect --respawn src/server.ts",

    "build": "rimraf build && tsc -p tsconfig.json",
    
    "test": "NODE_ENV=test nyc ./node_modules/.bin/mocha --require ts-node/register ./src/test/**/**/**/**/*.test.ts",
}

Your tsconfig.json compilerOptions should look something like this:

"compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "lib": ["es2015", "dom"],
    "sourceMap": true,                       
    "outDir": "./build",

    "strict": true,
    "strictPropertyInitialization": false,

    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,

    "moduleResolution": "node",
    "types": ["reflect-metadata"],
    "esModuleInterop": true,
    "inlineSources": true,

    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "skipLibCheck": true
}

PM2 can generate startup scripts and configure them to keep your process list intact across expected (and unexpected) machine restarts. This is important to keep automated. https://pm2.keymetrics.io/docs/usage/startup/

pm2 unstartup
pm2 startup
pm2 save
GROVER.
  • 4,071
  • 2
  • 19
  • 66
Ivan Proskuryakov
  • 1,625
  • 2
  • 23
  • 32
  • 2
    One of the first things it says on that page: `We highly don’t recommend to use this in production as it slows down your app` – CaribouCode Jun 23 '20 at 18:18
  • Agree, I also seen it, but its questionable a. It could be just downtime that takes transpiling and no benchmarks. b. Also, it may be needed to run "production" environment on a staging server, where speed issue is not crucial. – Ivan Proskuryakov Jun 25 '20 at 08:54
  • 1
    @CaribouCode That's good to note but for some applications, it just doesn't matter. I'm working on a private chat bot. For that situation, it's not worth the overhead of dealing with the dev overhead of compiling. – Tim Jan 24 '21 at 22:51
5

The package.json script should be like below:

package.json file (containing below example scripts)

"scripts": {
    "shivkumarscript": "ts-node -T -P server/tsconfig.json server/index.ts"
  }

ecosystem.config.js file

module.exports = {
    apps: [
        {
            name: "NodeServer",
            script: "npm",
            automation: false,
            args: "run shivkumarscript",
            env: {
                NODE_ENV: "development"
            },
            env_production: {
                NODE_ENV: "production"
            }
        }
    ]
}

Assuming that you have already installed Node.js, npm and PM2 on your machine. Then below should be the command to start the application through pm2 which will in turn run the npm script (command line mentioned in your application's package.json file):

For production environment:

pm2 start ecosystem.config.js --env production --only NodeServer

For development environment:

pm2 start ecosystem.config.js --only NodeServer
E_net4
  • 27,810
  • 13
  • 101
  • 139
Shiv
  • 3,069
  • 1
  • 24
  • 17
2

I did a simple solution, using the pm2 config file in the project root:

project
│   pm2.config.js
│   package.json  
│   tsconfig.json    
│
└───src
│   │   index.ts
└───dist
    │   index.js

pm2.config.js

module.exports = {
    apps: [
        {
            name: 'My Application',
            script: './dist/index.js',
        },
    ],
};

package.json

"scripts": {
 "dev": "ts-node-dev --respawn --transpile-only ./src/index.ts",
 "start": "tsc && node ./dist/index.js",
 "pm2": "tsc && pm2 start pm2.config.js"
}

note: you can also add && pm2 save to the pm2 script if you wish

now in dev, type: npm run dev and in production, register to pm2 with npm run pm2

tomer953
  • 229
  • 2
  • 6