Node.js supports two module systems, and most confusing errors in student projects come from mixing them.
- CommonJS (the older default): const fs = require('fs') and module.exports = something. Loaded synchronously.
- ES modules (the JavaScript standard): import fs from 'fs' and export default something. Supports top-level await.
How Node decides
- Files ending in .mjs are ES modules; files ending in .cjs are CommonJS.
- For .js files, Node looks at the nearest package.json: "type": "module" means ES modules; no type field means CommonJS.
import { readFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
const me = fileURLToPath(import.meta.url);
const text = await readFile(me, 'utf8');
console.log('top-level await works here:', text.includes('top-level'));top-level await works here: trueErrors that mean you mixed them
- "require is not defined in ES module scope": you used require in an ES module. Use import, or rename the file to .cjs.
- "Cannot use import statement outside a module": you used import in a CommonJS file. Add "type": "module" to package.json or rename the file to .mjs.
- __dirname and __filename do not exist in ES modules; build them from import.meta.url as above (newer Node versions also offer import.meta.dirname).
For new projects, ES modules are the direction the ecosystem is moving. Prefix built-in modules with node: (as in node:fs) so it is obvious they are not npm packages.
#nodejs#modules#require#import
Sources and further reading
Practise this as an interview question
Written by the UniCircle team, checked by an editor on 22 Oct 2026. It is not official policy of any university. Exam patterns and rules change; confirm dates and rules on the official website.
