First, My current setup works locally. I've been stuck on this problem for days.
Second, I'll describe it by sections
- directory structure
- typescript setup (tsconfig + path mappings)
- setup related to
module-aliaspackage + package.json - step how i deploy to heroku
- the error log by heroku
Directory structure
├── client/
│ ├── src
│ └── package.json
├── server/
│ ├── tsconfig.json
│ └── package.json
└── shared/
├── helpers/validators.ts
├── constants/tags.ts
└── models/bookmark.ts
tsconfig setup
Note: I'm using path mappings/alias set in tsconfig.json. I installed the package module-alias for the compiled files to be able to find the path mappings.
On my tsconfig, i'm importing a file that is outside the typescript project where tsconfig.json is located
As you can see on the directory structure, the tsconfig.json is under server folder and i'm importing files from the shared folder
So here's my tsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@models/*": ["../shared/models/*"],
"@constants/*": ["../shared/constants/*"],
"@helpers/*": ["../shared/helpers/*"]
},
"target": "es2018",
"module": "commonjs",
"moduleResolution": "node",
"rootDir": "../",
"outDir": "./build",
"esModuleInterop": true,
"strict": true,
"typeRoots": ["node_modules/@types"],
"sourceMap": false,
"removeComments": true
},
"include": ["**/*", "../shared/**/*"]
}
package.json + setup related to module alias package
Note: the path for _moduleAliases is based on the path of the compiled javascript file
{
"name": "pocketlite-server",
"version": "1.0.0",
"engines": {
"node": "14.x",
"npm": "6.x"
},
"description": "",
"main": "index.js",
"_moduleAliases": {
"@models": "build/shared/models",
"@constants": "build/shared/constants",
"@helpers": "build/shared/helpers"
},
"scripts": {
"start:prod": "node build/server/index.js",
"start:staging": "export NODE_ENV=staging && nodemon -r tsconfig-paths/register index.ts",
"start:dev": "export NODE_ENV=development && nodemon -r tsconfig-paths/register index.ts",
"build": "tsc -p .",
"heroku-prebuild": "npm i --only=dev",
"lint": "eslint . --ext .ts",
"csrf": "npx http-server -c-1 -d false -o /csrf-test"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/cookie-parser": "^1.4.2",
"@types/cors": "^2.8.7",
"@types/express": "^4.17.7",
"@types/jsdom": "^16.2.3",
"@types/mongoose": "^5.7.36",
"@types/mongoose-delete": "^0.5.1",
"@types/mozilla-readability": "^0.2.0",
"@types/node": "^14.0.27",
"@types/passport": "^1.0.4",
"@types/passport-google-oauth20": "^2.0.3",
"@types/passport-jwt": "^3.0.3",
"@types/puppeteer": "^3.0.1",
"@types/turndown": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^3.8.0",
"@typescript-eslint/parser": "^3.8.0",
"dotenv": "^8.2.0",
"eslint": "^7.6.0",
"nodemon": "^2.0.4",
"ts-node": "^8.10.2",
"tsconfig-paths": "^3.9.0"
},
"dependencies": {
"@mozilla/readability": "^0.3.0",
"@types/cookie-session": "^2.0.41",
"@types/csurf": "^1.9.36",
"cookie-parser": "^1.4.5",
"cookie-session": "^1.4.0",
"cors": "^2.8.5",
"csurf": "^1.11.0",
"express": "^4.17.1",
"isomorphic-dompurify": "^0.6.0",
"jsdom": "^16.4.0",
"jsonwebtoken": "^8.5.1",
"module-alias": "^2.2.2",
"mongoose": "^5.9.28",
"mongoose-delete": "^0.5.2",
"passport": "^0.4.1",
"passport-google-oauth20": "^2.0.0",
"passport-jwt": "^4.0.0",
"puppeteer": "^5.2.1",
"puppeteer-extra": "^3.1.15",
"puppeteer-extra-plugin-adblocker": "^2.11.6",
"puppeteer-extra-plugin-stealth": "^2.6.1",
"turndown": "^6.0.0",
"turndown-plugin-gfm": "^1.0.2",
"typescript": "^4.0.3"
}
}
Steps how I deploy in hero
- heroku create pocketlite-server
- heroku buildpacks:set heroku/nodejs
- heroku git:remote -a pocketlite-server
- git subtree push --prefix server heroku master
The error log in heroku
relevent npm scripts for heroku
"scripts": {
"start:prod": "node build/server/index.js",
"start:staging": "export NODE_ENV=staging && nodemon -r tsconfig-paths/register index.ts",
"start:dev": "export NODE_ENV=development && nodemon -r tsconfig-paths/register index.ts",
"build": "tsc -p .",
"heroku-prebuild": "npm i --only=dev"
}
Error log
-----> Node.js app detected
-----> Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
NPM_CONFIG_PRODUCTION=false
NODE_ENV=production
NODE_MODULES_CACHE=true
NODE_VERBOSE=false
-----> Installing binaries
engines.node (package.json): 14.x
engines.npm (package.json): 6.x
Resolving node version 14.x...
Downloading and installing node 14.13.0...
Bootstrapping npm 6.x (replacing 6.14.8)...
npm 6.x installed
-----> Prebuild
Running heroku-prebuild
> pocketlite-server@1.0.0 heroku-prebuild /tmp/build_8e06db38
> npm i --only=dev
> nodemon@2.0.4 postinstall /tmp/build_8e06db38/node_modules/nodemon
> node bin/postinstall || exit 0
Love nodemon? You can now support the project via the open collective:
> https://opencollective.com/nodemon/donate
added 194 packages from 194 contributors and audited 665 packages in 7.23s
19 packages are looking for funding
run `npm fund` for details
found 2 high severity vulnerabilities
run `npm audit fix` to fix them, or `npm audit` for details
-----> Installing dependencies
Installing node modules
> puppeteer@5.2.1 install /tmp/build_8e06db38/node_modules/puppeteer
> node install.js
> nodemon@2.0.4 postinstall /tmp/build_8e06db38/node_modules/nodemon
> node bin/postinstall || exit 0
Love nodemon? You can now support the project via the open collective:
> https://opencollective.com/nodemon/donate
added 661 packages in 19.572s
-----> Build
Running build
> pocketlite-server@1.0.0 build /tmp/build_8e06db38
> tsc -p .
helpers/link-scraper.ts(12,26): error TS2307: Cannot find module '@models/bookmark.model' or its corresponding type declarations.
helpers/validators.ts(1,23): error TS2307: Cannot find module '@constants/patterns' or its corresponding type declarations.
models/bookmark-favorite.ts(2,34): error TS2307: Cannot find module '@models/bookmark-favorite.model' or its corresponding type declarations.
models/bookmark.ts(7,26): error TS2307: Cannot find module '@models/bookmark.model' or its corresponding type declarations.
models/tag.ts(2,21): error TS2307: Cannot find module '@models/tag.model' or its corresponding type declarations.
models/user.ts(2,22): error TS2307: Cannot find module '@models/user.model' or its corresponding type declarations.
routes/bookmarks.ts(4,32): error TS2307: Cannot find module '@constants/tags' or its corresponding type declarations.
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! pocketlite-server@1.0.0 build: `tsc -p .`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the pocketlite-server@1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /tmp/npmcache.tNTfH/_logs/2020-10-04T01_44_27_692Z-debug.log
-----> Build failed
We're sorry this build is failing! You can troubleshoot common issues here:
https://devcenter.heroku.com/articles/troubleshooting-node-deploys
Some possible problems:
- A module may be missing from 'dependencies' in package.json
https://devcenter.heroku.com/articles/troubleshooting-node-deploys#ensure-you-aren-t-relying-on-untracked-dependencies
Love,
Heroku
! Push rejected, failed to compile Node.js app.
! Push failed
Update:
- I have also tried to dockerize my app, and the same error still occurs.
- I've discovered that it is related to typescript not resolving path mappings to their corresponding paths without a module bundler that rewrites path like webpack (w/c i don't use currently). Here's the relevant discussion in typescript's github issue