How JavaScript code gets split, shared, and loaded across files.
Before ES modules, JavaScript had no built-in way to split code across files with real isolation — CommonJS (Node's require/module.exports) and AMD filled that gap with different tradeoffs, both resolving and loading modules dynamically at runtime. ES modules (import/export) standardized this at the language level, and critically, they're statically analyzable: imports and exports must be declared at the top level, which lets tools determine the entire dependency graph without running any code.
That static structure is what makes tree-shaking possible — a bundler can see exactly which exports are actually used and strip out the rest, something CommonJS's dynamic require() calls make much harder to do reliably. ES modules also behave differently in subtle ways: they're automatically in strict mode, they're loaded once and cached (re-importing returns the same module instance), and top-level await lets a module pause on an async operation before anything that imports it can proceed.
What you'll walk away knowing
No questions match "".