Course:Node.js & Express/
Lesson

You will encounter two different syntaxes for importing code in Node.js projects. One uses require(), the other uses import. They look similar, they accomplish the same goal, but they are fundamentally different systems with different rules. AI mixes them constantly, producing code that throws confusing errors like SyntaxError: Cannot use import statement in a module or ReferenceError: require is not defined. Understanding why both exist and how they differ saves you hours of debugging AI-generated code.

Why two moduleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. systems exist

When Node.js was created in 2009, JavaScript had no built-in module system. The language had no import or export keywords. Node.js invented its own solution: CommonJSWhat is commonjs?Node.js's original module format using require() and module.exports - distinct from and predating the ES module import/export syntax..

// CommonJS (Node.js original)
const express = require('express');
const { readFile } = require('fs');

module.exports = { myFunction };
module.exports = myFunction;       // default export

In 2015, JavaScript (ES6) added a native module system: ES ModulesWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json. (ESM). Browsers adopted it. But Node.js already had millions of packages using CommonJS, so both systems had to coexist.

// ES Modules (modern standard)
import express from 'express';
import { readFile } from 'fs';

export { myFunction };
export default myFunction;
FeatureCommonJS (require)ES Modules (import)
Introduced2009 (Node.js)2015 (ES6 standard)
LoadingSynchronousAsynchronous
When parsedAt runtime (dynamic)At parse time (static)
Tree-shakableNoYes (bundlers can remove unused exports)
Default in Node.jsYes (without "type": "module")Only with "type": "module"
Works in browsersNoYes (with <script type="module">)
File extension hint.cjs forces CommonJS.mjs forces ES Modules
02

How Node.js decides which system to use

Node.js does not guess. It follows a clear decision tree:

  1. Is the file extension .mjs? Use ES ModulesWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json..
  2. Is the file extension .cjs? Use CommonJSWhat is commonjs?Node.js's original module format using require() and module.exports - distinct from and predating the ES module import/export syntax..
  3. Is the file extension .js? Check the nearest package.json:
  • If "type": "module" is set, use ES Modules.
  • If "type": "commonjs" is set (or the field is missing), use CommonJS.

This means the "type" field in package.json controls the behavior of every .js file in the project. One small change flips the entire moduleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. system.

json
// package.json
{
  "type": "module"   // all .js files use import/export
}
json
// package.json
{
  "type": "commonjs"  // all .js files use require/module.exports
  // (this is also the default if "type" is absent)
}
AI pitfall
AI generates import statements in projects that do not have "type": "module" in package.json. The code looks correct, but Node.js throws SyntaxError: Cannot use import statement in a module because it defaults to CommonJS mode. When you see this error in AI-generated code, check package.json first.
03

The mixing problem

The most common moduleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. bug in AI code is mixing require and import in the same file or the same project without proper configuration.

// ERROR: mixing systems in one file
import express from 'express';
const cors = require('cors');     // SyntaxError in ESM mode

// ERROR: using import without "type": "module"
import { readFile } from 'fs';    // SyntaxError in CJS mode

Node.js does not allow mixing within a single file. You must pick one system per file. However, ESMWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json. files can import CommonJSWhat is commonjs?Node.js's original module format using require() and module.exports - distinct from and predating the ES module import/export syntax. packages (most npm packages are CommonJS), and CommonJS files can dynamically import ESM packages using await import().

// ESM file importing a CommonJS package - works fine
import lodash from 'lodash';   // lodash is CJS, Node.js handles it

// CJS file importing an ESM-only package - requires dynamic import
const chalk = await import('chalk');  // chalk v5+ is ESM-only
ScenarioWorks?Notes
ESM file imports CJS packageYesMost common case, Node.js wraps CJS as default export
CJS file requires CJS packageYesTraditional Node.js
CJS file requires ESM packageNoMust use await import() instead
ESM file imports ESM packageYesThe future standard
Mixing require and import in one fileNoPick one per file
04

Default vs named exports

Both systems support exporting a single "default" thing and multiple "named" things, but the syntax differs and the interop between systems has quirks.

CommonJSWhat is commonjs?Node.js's original module format using require() and module.exports - distinct from and predating the ES module import/export syntax. exports

// Named exports
module.exports.add = (a, b) => a + b;
module.exports.subtract = (a, b) => a - b;

// OR using an object
module.exports = { add, subtract };

// Default-style export (the entire module.exports is one thing)
module.exports = function calculator() { /* ... */ };

ES ModuleWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json. exports

// Named exports
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }

// Default export
export default function calculator() { /* ... */ }

// Named import
import { add, subtract } from './math.js';

// Default import
import calculator from './math.js';

// Import everything
import * as math from './math.js';

The interop gotcha

When you import a CommonJS moduleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. from an ESM file, Node.js wraps the entire module.exports object as the default exportWhat is default export?A module's single primary export, imported without curly braces and with any local name the caller chooses.. This mostly works, but named imports from CJS modules can behave unexpectedly.

// utils.cjs (CommonJS)
module.exports = { add, subtract };

// app.mjs (ESM)
import utils from './utils.cjs';         // works: utils.add, utils.subtract
import { add } from './utils.cjs';       // might NOT work in all Node versions
AI pitfall
AI generates import { something } from 'package' for CommonJS packages where named imports are not supported. If you get SyntaxError: Named export 'something' not found, the package is likely CJS. Switch to import pkg from 'package' and destructure after: const { something } = pkg.
05

The __dirname problem

In CommonJSWhat is commonjs?Node.js's original module format using require() and module.exports - distinct from and predating the ES module import/export syntax., __dirname and __filename are global variables that give you the current file's directory and path. In ES ModulesWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json., they do not exist.

// CommonJS - works
const configPath = path.join(__dirname, 'config.json');

// ES Modules - __dirname is not defined
// Use import.meta instead:
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const configPath = path.join(__dirname, 'config.json');

This is ugly but necessary. AI frequently generates code with __dirname in ESM files, which crashes at runtimeWhat is runtime?The environment that runs your code after it's written. Some languages need a runtime installed on the machine; others (like Go) bake it into the binary.. When you see __dirname in a project with "type": "module", it needs the import.meta workaround.

06

Choosing a moduleWhat is module?A self-contained file of code with its own scope that explicitly exports values for other files to import, preventing name collisions. system for new projects

For new projects in 2024+, ES ModulesWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json. are the standard. Set "type": "module" in package.json and use import/export everywhere. The ecosystem has largely caught up, most actively maintained packages support ESM.

For existing CommonJSWhat is commonjs?Node.js's original module format using require() and module.exports - distinct from and predating the ES module import/export syntax. projects, there is no urgent need to migrate. Both systems work. The only reason to switch is if you want tree-shaking (bundlers can eliminate unused ESM exports) or if a dependencyWhat is dependency?A piece of code written by someone else that your project needs to work. Think of it as a building block you import instead of writing yourself. you need is ESM-only.

SituationRecommendation
New projectUse ESM ("type": "module")
Existing CJS projectKeep CJS unless you have a reason to switch
Package published to npmShip both CJS and ESM for maximum compatibility
Quick script or CLI toolEither works, CJS is simpler for one-off scripts

When reviewing AI-generated code, the first thing to check is consistency. Is the project using require or import? Does package.json have the right "type" field? Are all files using the same system? If AI mixed them, you know exactly where the bug is.