Search code examples
typescriptherokudeploymenttsc

Why doesn't tsc run in Heroku?


I have a React Express TypeScript app which I've been struggling to deploy to Heroku. The aim is to deploy the app without manually creating the client build (React script) and server dist (tsc) folders, i.e. those folders should be built during deployment in Heroku. At the moment, the build folder is successfully built, but not the dist folder. I have double checked this by running the deployed app in bash mode and going through the folders. It seems like tsc does not run on the server side, but there are no warnings or errors regarding this during deployment.

To give some overview, I have the following folder structure (many folders and files left out for brevity):

|-- client
|   |-- public
|   |-- src
|   |-- package.json
|   '-- tsconfig.json
|-- server
|   |-- dist <-- **THIS FOLDER DOES NOT BUILD DURING DEPLOYMENT**
|   |-- src
|   |-- package.json
|   '-- tsconfig.json
'-- package.json

My package.json file (in the root folder) looks like this:

{
  ... ,
  "scripts": {
    "start": "node server/dist/index.js",
    "tsc": "tsc",
    "build": "react-scripts build",
    "heroku-prebuild": "npm install --prefix server && npm install --prefix client",
    "heroku-postbuild": "NPM_CONFIG_PRODUCTION=false && NODE_ENV=production && npm run tsc --prefix server && npm run build --prefix client"
  },
  ... ,
  "engines": { 
    "node": "12.13.1",
    "npm": "6.12.1"
  }
}

...and the server/tsconfig.json file looks like this:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true 
  },
  "exclude": [
    "dist",
    "node_modules"
  ],
  "include": [
    "src"
  ]
}

My understanding is that npm run tsc --prefix server in heroku-postbuild should do the trick, but it doesn't. I am probably missing something here. Maybe my folder structure is not correct, but I feel like that should not be an issue to get the app deployed.

I would be thankful to get any help or pointers to the right direction.

Edit: I should also mention that TypeScript has been add as a dependency in server/package.json:

{
  ...,
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^4.2.0",
    "eslint": "^7.9.0",
    "eslint-config-airbnb-base": "^14.2.0",
    "eslint-plugin-import": "^2.22.0",
    "nodemon": "^2.0.4"
  },
  "dependencies": {
    "@types/chai": "^4.2.13",
    "@types/express": "^4.17.8",
    "@types/jest": "^26.0.14",
    "@types/socket.io": "^2.1.11",
    "@types/socket.io-client": "^1.4.34",
    "@types/supertest": "^2.0.10",
    "@typescript-eslint/parser": "^4.4.1",
    "body-parser": "^1.19.0",
    "chai": "^4.2.0",
    "express": "^4.17.1",
    "jest": "^26.5.3",
    "socket.io": "^2.3.0",
    "socket.io-client": "^2.3.1",
    "supertest": "^5.0.0",
    "ts-jest": "^26.4.1",
    "typescript": "^4.0.3"
  }
}

Solution

  • I still haven't managed to find a solution. So I ended up with a workaround. In case someone is struggling with the same thing, what I did was to run tsc manually on the server to create the server/dist folder. It is not the solution I was looking for, but it works for now.