15

I am trying to deploy a sample of the Angular Universal Starter in Heroku.

The task npm start fails because it does not recognize ts-node.

Is there a way to make deployment on Heroku work using ts-node?

Joao Garin
  • 573
  • 1
  • 5
  • 16

9 Answers9

18

You can create a Procfile with

web: npm start

And have your start script to run ts-node

"start": "ts-node src/index.ts",

And install typescript and ts-node on your dependencies

"ts-node": "^3.3.0",
"typescript": "^2.4.2"
BrunoLM
  • 97,872
  • 84
  • 296
  • 452
  • I get this error since the last build, and did not change `ts-node`. However, ts-node is in `"devDependencies"` and not `dependencies` in package.json, and was it before the error. I deleted `@babel/core` npm package. – Timo Aug 06 '22 at 14:21
  • I think the `devdep` is my problem as seen [here further down](https://stackoverflow.com/a/70891715/1705829) – Timo Aug 06 '22 at 14:38
2

You can't deploy ts-node to heroku directly. either build your own buildpack or just compile typescript to javascript. I recommend the latter. Just run the command tsc -p . on publish.

Edit You can also create a file called index.js and add the following:

require('ts-node/register');
require('./server.ts');

Then it should work. Don't forget to run npm install --save-dev ts-node as well.

This is not recommended in production environment. Use it only in development.

Louay Alakkad
  • 7,132
  • 2
  • 22
  • 45
  • Hello Louy, Thank you for your answer.I will try this out. Regarding the latest statement, what is not safe? Using heroku to run the typescript app in production? – Joao Garin Dec 13 '15 at 08:37
  • Your suggestion works nicely locally but I still get an Application Error on heroku. I have in my package.json all the dependencies and the follwoing settings "main": "index.js", "scripts": { "start": "node index.js" }, "engines": { "node": "0.12.7" }, – Joao Garin Dec 13 '15 at 09:24
  • From the logs I get the following : Error: Cannot find module 'ts-node/register' – Joao Garin Dec 13 '15 at 09:40
  • 1
    I meant you shouldn't use "ts-node" in production. performance-wise it's a bad idea. To get it to work in heroku run this: `npm install --save ts-node`. What I suggest is doing a build step before running the app in heroku. – Louay Alakkad Dec 13 '15 at 16:53
  • Okay thank you for your help! I am only running as a development so I guess its fine. – Joao Garin Dec 14 '15 at 20:42
  • 1
    @Louy could you please explain why "performance-wise it's a bad idea"? I thought that ts-node will parse the typescript once, and then run the code without any different than javascript? – Huan Jul 30 '16 at 15:29
  • @zixia it will. it's just the parsing step; plus it will have the TS compiler in memory all the time. – Louay Alakkad Jul 30 '16 at 20:30
  • @Louy got it, thanks. so if I do not mind slow on start time and waste some memory, it should be ok. good news for me. :) – Huan Aug 01 '16 at 17:21
2

package.json :

"start":"ts-node index.ts",
"dependencies": { "ts-node" : "~<version number>" }

work for me :)

nadav
  • 552
  • 5
  • 11
2

To resolve problem in heroku related to missing ts-node you need to build your TypeScript code using tsc command in your package.json.

 "scripts": {
    ...
    "build": "tsc",
  }

Then in Procfile you can use node command to run files that Heroku build for you by ruunning build command in package.json.

web: node dist/src/server.js

Personally, I think that's a best solution for deployment a TypeScript-based application to Heroku, if you need also tsconfig.json you can take a look for mine.

{
  "extends": "@araclx/tsconfig",
  "compilerOptions": {
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "noUnusedParameters": false,
    "noUnusedLocals": false,
    "lib": ["ES2018"],
    "module": "commonjs",
    "target": "es6",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist"
  }
}
keinsell
  • 426
  • 5
  • 16
2

Maybe I'm late, but I was running into the same issue this week and this is what I've done to solve the issue by gathering multiple solutions in the web. Hope it helps someone:

Added the node and yarn or npm versions to package.json

  "engines": {
    "node": "12.14.0",
    "yarn": "1.x"
  },

Added ts-node and typescript to the project dependencies on the package.json

"ts-node": "^9.0.0",
"typescript": "^4.1.2"

Added the postinstall script that is called after the yarn or npm install called by Heroku, this will build your app on the chosen destination folder (dist in this case)

And changed the start script to server the compiled app instead of the TS one

  "scripts": {
    "postinstall": "tsc",
    "start": "cross-env NODE_ENV=production node dist/index.js"
  },

Pointed to the start script on the PROCFILE

web: yarn start

And finally this is the tsconfig.json where you can choose the build destination "outDir": "dist",

{
    "compilerOptions": {
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "target": "es2018",
        "moduleResolution": "node",
        "module": "commonjs",
        "sourceMap": true,
        "rootDir": "src",
        "outDir": "dist",
        "lib": ["esnext", "dom", "es2018", "esnext.asynciterable"],
        "esModuleInterop": true
    },
    "exclude": ["node_modules"]
}
uhum
  • 177
  • 2
  • 8
2

For unknown reasons Heroku prunes ts-node as dev dependency even if you listed it in dependencies instead of devDependencies. What should you do is to instruct Heroku not to prune devDependencies with the command:

  $ heroku config:set NPM_CONFIG_PRODUCTION=false YARN_PRODUCTION=false
Anynomius
  • 211
  • 2
  • 4
2

I recently ran into this issue in 2022, and this was the top answer, so i am adding my solution.

First; to dispel the myth you shouldn't use ts-node in production . .

refer to this answer from @Benny Neugebauer quoted here:

According to Blake Embrey, the author of ts-node, you can use it in production BUT you should use it with the `--transpile-only flag.

Example:

ts-node --transpile-only ./src/start.ts

Additionally, you should remove .ts from "start": "src/start.ts" in package.json and add typings as per the typescript doc

...
    "start":   "ts-node --transpile-only ./src/start",
    "typings": "src/start",
...

AND you also follow the instructions to have your tsconfig file include the following:

    "compilerOptions": {
...
    /* Strict Type-Checking Options */
    "strict": false,                                 /* Enable all strict type-checking options. */
...
    },
  "exclude": ["node_modules"]

and you still get an error

The Real Problem:

If you are using a basic configuration for a heroku-22 server, free or hobby and switch from a node to TS build, you may notice the errors on production after deployment and startup that look something like this:

TSError: ⨯ Unable to compile TypeScript:
 server.ts(1,29): error TS7016: Could not find a declaration file for module 'body-parser'. '/app/node_modules/body-parser/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/body-parser` if it exists or add a new declaration (.d.ts) file containing `declare module 'body-parser';`
 src/app.ts(2,26): error TS7016: Could not find a declaration file for module 'express'. '/app/node_modules/express/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/express` if it exists or add a new declaration (.d.ts) file containing `declare module 'express';`
...
diagnosticCodes: [ 7016, 7016, 2307, 7016 ]
Process exited with status 1
State changed from starting to crashed
...

The issue is that Heroku Buildpack heroku/nodejs is what is used by the angular/universal-starter uses does not have the ability to run ts-node without one extra step...

heroku config:set NPM_CONFIG_PRODUCTION=false YARN_PRODUCTION=false --app <YOUR_APP_NAME>

Mentioned by @anynomius in their answer here is what finally helped me and fixed the issues I was having.

Beau Bouchard
  • 835
  • 11
  • 28
1

For our project, the problem was, that ts-node was only in devDependencies in the package.json, but Heroku needs this dependency at runtime so it should be added in dependencies.

Chris L.
  • 11
  • 4
0

Below Solution that work for me

Step: 1 - Install below two package

npm i ts-node typescript --save-prod

Step 2: - Add the Below script to package.json inside scripts

"scripts": {
    "start": "npm index.js",
    "heroku-start": "ts-node \"./src/server.ts\"",
}

Step 3: - Add the below command in your Procfile (which exists at your root level)

web: npm run heroku-start

Step 4: Commit your changes and deploy on Heroku

enter image description here

Abdullah
  • 2,393
  • 1
  • 16
  • 29