Error [ERR_UNSUPPORTED_DIR_IMPORT]: Nodejs App cannot be started locally due to a directory import issue

My journey to deploy my app on Heroku has hit a roadblock. The import statements, like import cors from 'cors', are causing the app to fail in production with the "Cannot Load ES6 Modules in Common JS" error. Interestingly, everything runs smoothly locally.

Trying to fix this issue by adding

"type": "module"
to my package.json results in a new set of errors that prevent the app from running locally. I suspect the problem lies in how I'm setting up sequelize and its models, but I can't be certain. I need help with the correct syntax for imports to resolve this issue...I think.

The errors along with snippets from package.json and index.js are provided below.

Error Text

[nodemon] starting `babel-node src/index.js`
internal/process/esm_loader.js:74
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/Users/jeff/Clients/Bummer/Code/Server/src/models' is not supported resolving ES modules imported from /Users/jeff/Clients/Bummer/Code/Server/src/index.js
    at finalizeResolution (internal/modules/esm/resolve.js:272:17)
    at moduleResolve (internal/modules/esm/resolve.js:699:10)
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:810:11)
    at Loader.resolve (internal/modules/esm/loader.js:85:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:229:28)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:51:40)
    at link (internal/modules/esm/module_job.js:50:36) {
  code: 'ERR_UNSUPPORTED_DIR_IMPORT',
  url: 'file:///Users/jeff/Clients/Bummer/Code/Server/src/models'
}
[nodemon] app crashed - waiting for file changes before starting...

Package.JSON

{
  "name": "bummer",
  "type": "module",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node src/index.js",
    "dev": "nodemon --exec babel-node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  // other properties omitted for brevity
}

Index.js

import cors from 'cors';
import express from 'express';
import models, { sequelize } from './models';
// import routes from './routes';

//Initiaze Express
const app = express();
const routes = require('./routes');

//Helpers for Spotify oAuth
const cookieParser = require('cookie-parser')

// Include Middleware
app.use(express.static(__dirname + '/public'))
   .use(cors())
   .use(cookieParser())
   .use(express.json())
   .use(express.urlencoded({ extended: true }))
   require('dotenv').config()

// Include all Models
app.use((req, res, next) => {
  req.context = {
    models,
  };
  next();
});

// Load Routes from Router Index
app.use('/', routes);

sequelize.sync().then(() => {
  app.listen(process.env.PORT, () => {
    console.log(`Example app listening on port ${process.env.PORT}!`)
  });
});

Any insights or tips would be greatly appreciated! Thank you!

Answer №1

Specifically, indicate the primary file (typically index.js). Example:

import ... from './models'          // ❌
import ... from './models/index.js' // ✅

Different approach (refer to the following UPDATE):

Utilize the

--experimental-specifier-resolution=node
flag. Such as:

node --experimental-specifier-resolution=node main.js

Refer to: https://nodejs.org/api/esm.html#esm_customizing_esm_specifier_resolution_algorithm_unique


UPDATE (Node.js v19+):

Node.js has eliminated the

--experimental-specifier-resolution
flag. Its functionality can now be attained through custom loaders.

https://nodejs.org/en/blog/announcements/v19-release-announce/#custom-esm-resolution-adjustments_unique

The simplest loader (that only appends .js extension if necessary) is something like:

import {isBuiltin} from 'node:module'

// noinspection JSUnusedGlobalSymbols
export const resolve = (specifier, context, nextResolve) => // This function can be `async` too
  nextResolve(isBuiltin(specifier) || specifier.endsWith('.js') ? specifier : `${specifier}.js`, context)

Name it loader.js (or loader.mjs if you don't set yet

"type": "module"
in your package.json).

Then if you run your script (e.g. ./some-script.js) using this loader:

node --loader ./loader.js some-script.js

the imports within some-script.js (and the files imported in it) can omit .js extension.

See more complex examples: https://github.com/nodejs/loaders-test_unique


UPDATE (Node.js v20.8+): register()/--import:

Using register() function (from built-in node:module package) and then --import flag (instead of --loader):

There is a ts-loader example, in my other answer, using ts-node/esm (from ts-node library):

import {register} from 'node:module'
import {pathToFileURL} from 'node:url'

register('ts-node/esm', pathToFileURL('./'))

And then:

node --import ./ts-loader.js my-script.ts

It's originally for executing TypeScript files using Node.js. But it also works for the purpose of current question. It means you can execute your models/index.js (or models/index.ts), by:

node --import ./ts-loader.js models

Also, using it, you can run js/ts files w/o extension + running ts files with js extension (as you can import ts files in another ts file, using js extension)!

Answer №2

Node.js allows import statements within ES modules, limiting directory imports in Node.js. For more information on this topic, refer to the official Node.js documentation.

Answer №3

Consider including the

--experimental-specifier-resolution=node
parameter in your start command within the package.json file, especially if you are currently utilizing it for local operations - this specific command will be utilized by Heroku to launch your server.

scripts": {
    "start": "node --experimental-specifier-resolution=node index",
    ...
},

Answer №4

For an updated package.json file, consider including the following code:

"scripts": {
  "start": "node --experimental-specifier-resolution=node src/index"
}

Answer №5

Choice 1 "type" should be set to "module" before specifying "main":

Option: 2 Change the source file extension to .mjs

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for extracting a website's dynamic HTML content after AJAX modifications using Perl and Selenium

When dealing with websites that utilize Ajax or javascript to display data, I'm facing a challenge in saving this data using WWW::Selenium. Although my code successfully navigates through the webpage and interacts with the elements, I've encounte ...

Modifying the retrieval or storage object in mongodb

Here is the schema for my account: const account = new mongoose.Schema({ name: String, age: Number, coins: Number, phone: Number, sex: { type: String, default: 'f' } }, { timestamps: { ...

Executing Cross-Origin Resource Sharing in Angular and Node

I have implemented a frontend using Node.js and AngularJS, with the backend running on Jetty exposing REST services. I need to send a REST request from the frontend (Angular) to the backend. When I pass the complete URL to $http.get it works fine. However, ...

Replacing variables in a function: A step-by-step guide

I have frequently used the replace function to eliminate classes in JavaScript. Currently, I am working on creating a JavaScript function that allows me to remove a specific class from an element by passing in the element and the class name. changeAddress ...

Using Ajax to call a PHP function within a WordPress website

I am looking to trigger a PHP function using AJAX. Below is the code snippet of my form: <form class="woocommerce-form woocommerce-form-login login" method="post"> <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-ro ...

To retrieve a CSV file on the frontend, simply click a button in an AngularJS application that communicates with NodeJS and ExpressJS

How can I download a .csv file from the frontend? This is the code I am currently using: $http.get('/entity/consultations/_/registerationReport' ) .success(function (data) { myWindow = window.open('../entity/consultations/_/r ...

Modify values using the discord.js v13 command

I am currently developing a discord.js v13 bot, and I am looking to create a command that adds the channel ID where the command is executed to an existing variable. Additionally, I want to implement another command that specifically interacts with the chan ...

The pre-save function in Mongoose Schema fails to execute the next() function upon calling

In the process of developing a straightforward application that involves user sign up and login features, I have created the following user schema: // User Schema const userSchema = new mongoose.Schema({ username: { type: String, requ ...

Having trouble getting Vue.js hello world to display on the page

I am attempting to create a Hello World app following the Vue.js site's get started documentation. Everything seems to be in order, but only the HTML code is being displayed on the page. Vue version: 1.0.26 Below is the HTML code: <!DOCTYPE ht ...

Adding nested JSON data to MySQL using NodeJS

My current challenge involves using Node.js to INSERT JSON data into a MySQL database. Everything runs smoothly until I encounter nested values within the JSON structure. Here is an example snippet of my JSON data: var result2 = [{ "id": 89304, "employe ...

Retrieve information from an array within a blockchain smart contract

My smart contract factory has the ability to deploy another smart contract. Within the factory contract, there is a specific function: address[] public migrations; ... function getMigrations() public view returns (address[] memory) { return migr ...

Encountered a delay during the transfer of a file from storage to an FTP server via a cloud-based function

I'm currently facing an issue while attempting to transfer a file from storage to an FTP server using a triggered Node.js function. Every time a specific file is uploaded to Firebase storage, it should automatically be transferred to the FTP server. ...

Having trouble with the routes in my Express.js application

I recently started a personal express project where I created two separate files - one for the server (server.js) and another for handling routes (restaurants.route.js). However, I am facing an issue where I am unable to trigger the home route from localho ...

Setting up Nest.js on a Centos 7 server

While attempting to install nest.js on CentOS 7, I encountered the following error message: file:///usr/lib/node_modules/@nestjs/cli/node_modules/@nuxtjs/opencollective/src/index.js:7 ;(async () => { ^ SyntaxError: Unexpected token ( npm W ...

Error E11000: Key duplication detected in MongoDB database

I am facing an issue with my model as it keeps having errors after the first POST request. The project involves creating a scheduling application that spans over X number of days, each day having rooms and time slots for those rooms. The problem I am enco ...

Vue js throws a maximum call stack error when updating a Chart component

I have successfully created a line chart using the Chart.js 3.5 library. The chart is responsive, all animations are working fine too. I am currently facing an issue where I am attempting to update the data from a parent component and trigger a chart updat ...

When items are removed client-side, the Listbox becomes null

Given a Web Forms project inherited by me, I am relatively new to the field of Web development. The page in question features 2 listboxes: lstCaseLoad, containing "Caseloads" (ID numbers), and lstAssignedCaseLoad, filled with Caseloads chosen by the Form U ...

Is it possible to incorporate a next.js image onto the background design?

I've encountered an issue while attempting to create a fixed background image with a parallax effect using Tailwind CSS and Next.js Image. If you need to see an example of this in action, check out this Template Monster theme. Here's the code s ...

Why is the current Menu Item highlight feature not functioning properly?

Why isn't the highlight current Menu Item feature working? I've checked my code, but it doesn't seem to be functioning as expected. Could you lend me a hand? Html: <section id="menu-container"> <div id="bar"><img src="b ...

Receive JSON data with camel-case in a Web API 2.0 using a model in pascal-case style

My attempt to execute a PUT call on my Web API involves configuring the WebApiConfig.cs file to send data back to my Web project in camel case format. config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesCont ...