Lesson 25 of 80
Two competing module systems with genuinely different rules for loading, timing, and what an import actually is — not just different syntax for the same idea.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 2
A module does `export let count = 0` then later `count++`. A different file does `import { count } from './mod.js'`. After the increment, what does the importer see?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
// CommonJS (Node's original system)
const { add } = require("./math"); // synchronous, runs at the require() call
module.exports = { multiply };
// ES Modules (the language standard)
import { add } from "./math.js"; // hoisted, resolved before any code runs
export function multiply() {}
They look similar but differ in ways that actually matter:
require() runs synchronously, wherever you write it, like a function call. import statements are hoisted and resolved before the module's own code runs — you can't conditionally import inside an if.require() gives you a copy of module.exports at that moment. ES Modules exports are live bindings — if the exporting module later changes the exported variable, every importer sees the new value.require() can be called conditionally or computed at runtime, so bundlers can't always know the full graph ahead of time.const { add } = require('./math') — runs synchronously, exactly where it's written.
require() calls make that analysis unreliable.import is hoisted, require() is not. You can call require() conditionally inside an if; a top-level import statement can't be conditional (dynamic import() — the function form — exists specifically for that case)..mjs/.cjs extensions or the "type" field in package.json — mixing them incorrectly is a common real-world source of confusing "require is not defined" or "Cannot use import" errors.Explaining why tree-shaking requires ESM (not just knowing the syntax difference) is what separates "used both" from "understands why the ecosystem moved to ES Modules."