What does it mean if an import cannot find the module but the file path and case sensitivity is correct? I'm sensing a NodeJS issue or config issue (babel? eslint?) rather than the JS itself. I've tried using Node v19 and v20 with no change. I've found this problem happening for two different cases:
- Module not found when file path leads to a directory that should default to index.js
import Inventory from '../../models'; - Module not found when file path excludes the supposedly implied .js extension
import { Inventory } from '../index';
It is fixed when I explicitly import the file. Example:
import { Inventory } from '../index.js';import Inventory from '../../models/Inventory.model.js';
Here's an example of the setup where /models directory has the index.js file and /models/Inventory directory has the Inventory.models.js but other imports listed above are giving "Module not found" even with the right file path and case sensitivity. All of my tests run and pass when I explicitly import my files, so I know the exports are all correct. Does this look on par to you?
To be sure my imports and exports are correct, here is /models/index.js
import Inventory from './Inventory/Inventory.model.js';
// define model relationships here
export { Inventory };
To be sure my exports are correct, this is the const export from /models/Inventory/Inventory.model.js
export default Inventory;
I also tested renaming the files and import statements to camel case instead of dot case, and the issue still persists, so it's not the issue either.
Edit: This is the /server/package.json:
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"watch": "nodemon",
"seed": "node config/seeds.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.2",
"mysql2": "^3.9.2",
"sequelize": "^6.37.1"
},
"devDependencies": {
"@faker-js/faker": "^8.4.1",
"nodemon": "^3.1.0",
"sequelize-mock": "^0.10.2",
"uuid": "^9.0.1"
}
}
...And the root package.json:
{
"name": "name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest",
"start": "node server/index.js",
"dev": "concurrently \"cd server && npm run watch\" \"cd client && npm start\"",
"install": "cd server && npm i && cd ../client && npm i",
"build": "cd client && npm run build"
},
"repository": {
"type": "git",
},
"keywords": [],
"jest": {
"testEnvironment": "node",
"transform": {
"^.+\\.js$": "babel-jest"
}
},
"devDependencies": {
"@babel/core": "^7.24.0",
"@babel/preset-env": "^7.24.0",
"@babel/register": "^7.23.7",
"babel-plugin-inline-dotenv": "^1.7.0",
"concurrently": "^8.2.2",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.33.2",
"jest": "^29.7.0",
"prettier": "^3.2.5",
"supertest": "^6.3.4"
}
}
Per the node.js import documentation,
To import a module by its name without the file extension (i.e. a bare specifier), the module must have an
exportsfield in itspackage.json.More information about import specifier resolutions can be found here.