gotchajavascriptMajor
ESM import requires file extensions in Node.js
Viewed 0 times
Node.js 14+ for ESM, 18+ for stable JSON import assertions
ESM importsfile extensionERR_MODULE_NOT_FOUNDCommonJS vs ESMtype module
nodejs
Error Messages
Problem
Node.js ESM (import/export) requires file extensions in import paths. import { foo } from './utils' fails with ERR_MODULE_NOT_FOUND — you must write './utils.js'. This is different from CommonJS require() and bundlers like webpack.
Solution
Always include the file extension in ESM imports:
// BAD in Node ESM
import { foo } from './utils'; // ERR_MODULE_NOT_FOUND
// GOOD
import { foo } from './utils.js'; // works
import data from './data.json' assert { type: 'json' }; // JSON needs assertion
// To enable ESM in Node:
// Option 1: Add "type": "module" in package.json
// Option 2: Use .mjs extension
// For TypeScript: import from .js even though source is .ts
import { foo } from './utils.js'; // TypeScript resolves to utils.ts
// BAD in Node ESM
import { foo } from './utils'; // ERR_MODULE_NOT_FOUND
// GOOD
import { foo } from './utils.js'; // works
import data from './data.json' assert { type: 'json' }; // JSON needs assertion
// To enable ESM in Node:
// Option 1: Add "type": "module" in package.json
// Option 2: Use .mjs extension
// For TypeScript: import from .js even though source is .ts
import { foo } from './utils.js'; // TypeScript resolves to utils.ts
Why
Node.js ESM follows the browser ESM spec, which requires explicit file extensions. CommonJS had special resolution logic (try .js, .json, .node, index.js) but ESM intentionally doesn't — it's explicit by design. Bundlers like webpack add their own resolution.
Gotchas
- TypeScript ESM: import from './file.js' even though the source file is .ts
- Directory imports (import './dir') don't work in ESM — need './dir/index.js'
- require() still works in CommonJS files alongside ESM
- JSON imports need 'assert { type: "json" }' in Node ESM
Code Snippets
ESM imports in Node.js
// package.json
{ "type": "module" }
// ESM requires extensions
import express from 'express'; // packages work without extension
import { helper } from './lib.js'; // local files NEED .js
import config from './cfg.json' assert { type: 'json' };Context
When migrating from CommonJS to ESM in Node.js projects
Revisions (0)
No revisions yet.