Search code examples
javascripttypescriptherokudiscord

Heroku doesn't deploy TypeScript Application


Problem

I've made a typescript discord bot and hosted it on heroku. I get the below error while compiling it and then running it.

  • Error:
Starting process with command `npm run dev`
State changed from starting to up
Process exited with status 127

> [email protected] dev
> run-s build start

sh: 1: run-s: not found
State changed from up to crashed
  • Procfile:
worker: npm run dev
  • package.json:
// ...
"scripts": {
        "build": "tsc",
        "watch": "tsc -w",
        "start": "node dist/index.js",
        "dev": "run-s build start",
        "watch:start": "tsc-watch --onSuccess \"node ./dist/index.js\"",
        "format": "prettier --write \"src/**/*.ts\""
},
"engines": {
        "node": "17.8.0"
}
// ...

Information

I'm deploying through Heroku CLI.

git push heroku main

Solution

  • Out of the box, in the absence of a Procfile, Heroku will run your build script at build time (when you deploy) and your start script as a web dyno at runtime (when your dyno starts).

    Your build and start scripts make sense, the former running tsc to compile your TypeScript to JavaScript and the latter running the compiled JavaScript.

    Since you want to run a worker process instead of a web process you need a Procfile, but this one hands the work off to the wrong script, using dev instead of start:

    worker: npm run dev
    

    Your dev script tries to build your already built application at runtime, which is a problem for a few reasons:

    • the immediate issue is that run-s is not available, probably because it was declared as a dev dependency
    • building here is redundant since your application was already compiled during deployment,
    • if it works at all, it's going to significantly delay startup every time your dyno restarts, you scale your application, etc.,
    • like run-s, tsc probably isn't available at runtime (and shouldn't be) because it was declared as a dev dependency

    Use your start script instead of your dev script:

    worker: npm run start