Modules & Bundling
The problem
As a codebase grows past one file, code needs a way to be split across files while still sharing functions and values between them in a controlled way — and browsers need that many-file codebase delivered efficiently as a small number of optimized network requests, not hundreds of individual files.
Why now
Functions and scope already established that a function's internals are hidden by default; modules apply that exact same hide-by-default, expose-deliberately principle at the level of an entire file, and bundling is the practical, network-aware step of combining many such files back into what a browser can load efficiently.
Mental model
A module is a file with its own private scope — nothing inside it is visible outside unless explicitly exported, the same encapsulation idea from functions-and-scope, just at file granularity instead of function granularity. A bundler is a build-time tool that walks the import graph (itself a dependency DAG) starting from an entry point and produces one or few optimized files for the browser to load instead of many small ones.
Requires
- Functions & ScopeProgramming Fundamentals
A module's scope isolation (nothing leaks out unless exported) is the identical hide-by-default principle already established for function scope, just applied to an entire file.
Helps
- Control FlowProgramming Fundamentals
Understanding how a bundler resolves an import graph (walking dependencies from an entry point) benefits from already thinking in terms of traversal, though it isn't strictly required to use import/export syntax.
Unlocks
Used in
- import/export syntax (ESM) and require() (CommonJS) — the two dominant JavaScript module systems
- Bundlers (Webpack, esbuild, Vite, Turbopack) that combine and optimize many files for production delivery
- Tree-shaking, which relies on static import/export analysis to remove unused code
- Code-splitting, loading only the modules a specific page actually needs
Projects
- Split a single-file script into three modules with explicit imports/exports, then bundle them and inspect the resulting output file
- Compare an app's bundle size before and after removing an unused import, and explain how tree-shaking achieved the reduction
Examples
- export function add(a, b) { return a + b } in math.js is only usable elsewhere via import { add } from './math.js'
- A bundler starting from index.js follows every import statement transitively to build the full set of files needed for one page
Resources
- MDN — JavaScript modulesarticle
Mastery checklist
- I can split code into modules using import/export and explain what stays private
- I can explain what a bundler does and why it's needed for production delivery
- I can explain tree-shaking at a high level and why it requires static (not dynamic) imports
- I can explain the difference between ESM and CommonJS module systems