AlgoInsight

Free lesson · JavaScript Basic to Advance

Why Modules Exist

Easy5 min read

What Modules Solve

A module is a file that exposes some of its values to other files and keeps the rest private. The exposed values become available when other files import them. Everything else stays inside the file, invisible to the rest of the program.

// math-utils.js — a module
export function add(a, b) {
  return a + b;
}

function privateHelper() {
  // not exported — invisible outside this file
}
// app.js — another module
import { add } from "./math-utils.js";

console.log(add(2, 3));   // 5
// privateHelper is not accessible here

This is the foundation of modern JavaScript architecture. Every real application is built from dozens or hundreds of modules. Understanding how they fit together is the difference between writing code that grows cleanly and code that turns into one giant file nobody wants to touch.

Olena here. Module 11 is my territory because the module system is where my self-taught background meets my Microsoft work on VS Code's remote development. When I first learned JavaScript in 2018, modules were the topic I felt most insecure about — every tutorial seemed to assume I already knew what they were and how they worked. This module is the resource I wish I'd had then.

Interactive animation: Last script wins, silently - every script tag shares one global scope, so a name declared twice is quietly replaced.

The Problem Before Modules

JavaScript didn't always have modules. From 1995 until roughly 2015, the language had no official module system at all. Code was either inline in <script> tags or loaded by including separate .js files.

<!-- The old way — early 2000s web -->
<script src="jquery.js"></script>
<script src="utils.js"></script>
<script src="app.js"></script>

Each <script> tag loaded a file. Everything that file declared at the top level became a global variable. By the time three or four scripts had loaded, the global scope was a mess — every variable, every function, every helper from every file all in one shared namespace. Naming collisions were common. Order of loading mattered. Loading order bugs were among the most common problems in early web development.

People worked around this with conventions. Libraries would wrap themselves in immediately-invoked function expressions (IIFEs) to create private scopes, exposing only a single global object — jQuery, $, Backbone. This kept the global namespace cleaner but didn't solve the structural problem. Code in one file still couldn't cleanly say "I need this specific thing from this specific other file."

Node.js, starting in 2009, was the first big environment to ship with a real module system — CommonJS, with require and module.exports. Browsers were slower. A standard for browser-friendly modules was debated for years. Finally, in 2015, ECMAScript 6 introduced ES Modules as the official language standard.

graph LR
    A[1995-2015<br/>No modules<br/>Globals everywhere] --> B[2009<br/>CommonJS in Node<br/>require/exports]
    B --> C[2015<br/>ES Modules<br/>import/export]
    C --> D[2020+<br/>ESM in browsers<br/>and modern Node]

    style A fill:#dc2626,color:#fff
    style B fill:#f59e0b,color:#fff
    style C fill:#10b981,color:#fff
    style D fill:#7c3aed,color:#fff
This diagram shows the evolution of JavaScript modules. For two decades, JavaScript had no module system at all — code shared a single global scope across all files in a page. In 2009, Node.js introduced CommonJS with require and module.exports as a server-side solution. In 2015, ES Modules became the official language standard with import and export syntax. By 2020, ES Modules became widely supported in both browsers and modern Node.js, becoming the standard way to structure JavaScript code.

Modern JavaScript uses ES Modules as the primary system. CommonJS still exists — it's the legacy of Node.js — but new code overwhelmingly uses the ES Module syntax. This module covers ES Modules first and CommonJS as the legacy you'll encounter in older codebases.

Interactive animation: The IIFE era at scale - privacy by closure, with one global object as each library's only export.

What Modules Give You

Three concrete benefits, all derived from the same idea — file-level scope:

1. Private state. Anything not exported is invisible outside the module. No more accidental global pollution. No more naming collisions across files. Each module is its own sandbox.

2. Explicit dependencies. When a module says import { add } from "./math-utils.js", it's declaring exactly what it needs and where it comes from. Reading a module's imports tells you everything that module depends on. No more "I'm using a global I forgot was defined."

3. Tools that understand structure. Bundlers, type checkers, IDE tooling, dead-code eliminators — they all need to know which file uses which other file. Modules give them that information explicitly. Without modules, every tool is reduced to text-level analysis. With modules, tools can do real structural work.

The third benefit is enormous in practice. When you write import { x } from "y", your editor can jump to the definition of x. Your bundler can include only what's used. Your type checker can verify the import. Your test framework can mock specific modules. All of this depends on modules being a real language feature, not just a convention.

Interactive animation: Not a list but a graph - imports are the edges between modules, and the loader walks them.

A Module Is a File

In ES Modules, the file is the module. There's no separate "module" declaration. Every .js file in a project is potentially a module. The decision of what to export and import lives inside the file itself.

This is different from some other languages. Java has explicit package declarations. Python lets you import sub-parts of a file. JavaScript keeps it simple: one file equals one module, no separate registration step.

What makes a file an ES Module specifically (versus a script):

Modern projects typically configure everything as ES Modules by default. If you're starting a new project today, you'll work in ES Modules. If you're reading old code, you'll see CommonJS — covered in Topic 11.5.

What This Module Will Build

The rest of Module 11 covers each part of the module system:

By the end, you should be able to read any module-using JavaScript codebase, write your own modules cleanly, and understand the npm ecosystem at the level needed for real work.

Common Pitfalls

Warning: The modules-mental-model traps.

Thinking modules are just "files with import." They're more than that — they have their own scope, their own strict mode, their own special rules (covered later in this module). Files without imports/exports are also modules in environments configured for ES Modules.

Mixing ES Modules and CommonJS without understanding the difference. Many projects have a mix of both for legacy reasons. The two systems are similar but have important differences in semantics. We'll cover this in Topic 11.5.

Confusing "global" with "module-scoped". Variables declared at the top of a module aren't global — they're local to that module. A var x at the top of a module file does NOT create a global x. This is one of the biggest differences from script files.

Why This Matters in Interviews

Interview: Module system questions are common at all interview levels. "How do you organize JavaScript code into modules?" is a beginner question. "What's the difference between ES Modules and CommonJS?" is intermediate. "Can you describe how import works under the hood?" is senior.

Topic 11.7 — Interview Lens: Module System Questions — covers the deeper interview-prep treatment.

Try It

Exercise: Take a single-file JavaScript program with a few functions and split it into modules. The exercise:

  1. Start with a 50-line script that has 3-5 functions and some global variables
  2. Identify which functions belong together logically
  3. Move each group into its own module file
  4. Add appropriate export and import statements
  5. Verify the program still works

The split doesn't have to be perfect — the goal is to feel the mechanical process of breaking code into modules. Once you've done this once, the rest of Module 11 will make more sense.

Back to JavaScript Basic to Advance