Error on Heroku: `SyntaxError: Cannot use import statement outside a module`


I encountered a very strange bug when I tried to deploy my node.js backend written in TypeScript to Heroku. The same set of code run perfectly in my local environment (and in all of my teammate’s local environment as well) but it failed on Heroku. The Heroku log gives me this error:

(node:4) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
import dotenv from "dotenv";
SyntaxError: Cannot use import statement outside a module

I looked up other stackoverflow post and they said I need to include "type": "module" in my package.json file in order to enable the import. However, doing that would give me another error:

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"

Essentially lost the ability to recognize .ts files if I want to have the import statements. I tried many things in different stackoverflow posts but they didn’t really work. So I stopped "fixing" my code, since my code run perfectly on local environments. I wonder if this is an issue with Heroku, is there a setting on Heroku that I can change so this code would work like my local environment?

Or is there a better way to fix the import statement issue while using TypeScript?

For your reference, here is my package.json file:

  "name": "booknbucks-backend",
  "version": "1.22.15",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "node app.ts",
    "dev": "nodemon app.ts",
    "build": "tsc",
    "production": "node dist/app.js"
  "dependencies": {
    "@types/dotenv": "^8.2.0",
    "@types/express": "^4.17.13",
    "@types/mongodb": "^4.0.7",
    "bcryptjs": "^2.4.3",
    "compression": "^1.7.4",
    "cors": "^2.8.5",
    "dotenv": "^16.0.0",
    "express": "^4.17.2",
    "firebase-admin": "^10.0.2",
    "helmet": "^5.0.2",
    "jsonwebtoken": "^8.5.1",
    "moment": "^2.29.1",
    "mongoose": "^6.2.0",
    "mongoose-paginate-v2": "^1.6.3",
    "node-cron": "^3.0.0",
    "typescript": "^4.6.3"

And here is my tsconfig.json file:

  "compilerOptions": {
    "module": "commonjs",
    "target": "esnext",
    "sourceMap": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "outDir": "dist",
    "baseUrl": "."
  "exclude": ["node_modules"],
  "include": ["**/*.ts"]


Your build script is running tsc, but your start script still tries to run the uncompiled .ts file instead of the compiled .js file.

Point it to the compiled file instead:

"start": "node dist/app.js",

Note that your Procfile will take precedence over your start script if it exists, so make sure to check there, too.

Answered By – Chris

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published