ES modules let you split JavaScript code across multiple files and explicitly control what each file shares with the rest of the app, using export to publish values and import to consume them elsewhere. This lesson covers named exports, default exports, aliasing with as, and namespace imports — the tools that make large codebases maintainable.
1JS Modules | JavaScript Tutorial - In-Depth Guide Part 1
As your apps grow, a single file becomes impossible to manage. Modules allow you to split your code into separate, reusable files.
// Modular Architecture2JS Modules | JavaScript Tutorial - In-Depth Guide Part 2
To share something from a file, use the ''export' keyword. You can export variables, functions, or even classes.
// mathUtils.js
export const add = (a, b) => a + b;
export const PI = 3.14;3JS Modules | JavaScript Tutorial - In-Depth Guide Part 3
To use those exported values in another file, use the ''import' keyword followed by the relative path to the module.
// main.js
import { add, PI } from './mathUtils.js';
console.log(add(10, PI));4JS Modules | JavaScript Tutorial - In-Depth Guide Part 4
You can also use ''export default' for the main value of a module. This allows the importer to choose any name they like.
// hero.js
export default class Hero { ... }
// app.js
import SuperHero from './hero.js';5JS Modules | JavaScript Tutorial - In-Depth Guide Part 5
Renaming: If you have a naming conflict, you can use the ''as' keyword to rename an import on the fly.
import { add as sum } from './math.js';
console.log(sum(5, 5));6JS Modules | JavaScript Tutorial - In-Depth Guide Part 6
Importing everything: Use the ''*' symbol to import all named exports from a file into a single namespace object.
import * as MathTools from './math.js';
MathTools.add(1, 2);7JS Modules | JavaScript Tutorial - In-Depth Guide Part 7
Modular Logic: By separating concerns, your code becomes easier to test, debug, and reuse across projects.
<h1>Code: Organized</h1>8JS Modules | JavaScript Tutorial - In-Depth Guide Part 8
Module mastery unlocked! You now know how to build clean, scalable application architectures.
<h1>App: Scalable</h1>9JS Modules | JavaScript Tutorial - In-Depth Guide Part 9
Next, we will explore 'Storage'—how to save data locally in the browser.
<h1>Next: LocalStorage</h1>10Step-by-Step Breakdown
As your apps grow, a single file becomes impossible to manage. Modules allow you to split your code into separate, reusable files.
To share something from a file, use the ''export' keyword. You can export variables, functions, or even classes.
To use those exported values in another file, use the ''import' keyword followed by the relative path to the module.
Checkpoint: When using Named Exports (like { add }), does the name in the import must match the name in the export?
- →Yes, names must match exactly
- →No, you can call them anything
You can also use ''export default' for the main value of a module. This allows the importer to choose any name they like.
Renaming: If you have a naming conflict, you can use the ''as' keyword to rename an import on the fly.
Checkpoint: How many ''Default Exports' can a single JavaScript file have?
- →As many as you want
- →Exactly one per file
Importing everything: Use the ''*' symbol to import all named exports from a file into a single namespace object.
Modular Logic: By separating concerns, your code becomes easier to test, debug, and reuse across projects.
Checkpoint: Which keyword is used to make a function available for use in other files?
- →import
- →export
- →public
Module mastery unlocked! You now know how to build clean, scalable application architectures.
Next, we will explore 'Storage'—how to save data locally in the browser.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Module Boundaries Don't Directly Affect the Accessibility Tree, But They Shape How Consistently Widgets Behave
Splitting a UI component's markup, styling, and ARIA logic across multiple modules can cause an accessible widget (like a custom combobox) to drift out of sync if one module updates its `aria-*` attributes but a sibling module doesn't — keep the interactive behavior and its accessibility state in the same module.
SEO Implications
- 1
ES Modules Enable Effective Code-Splitting, Which Improves Crawl and Load Performance
Because modules are explicit, bundlers like webpack and Rollup can perform tree-shaking (dropping unused exports) and route-based code-splitting, shipping smaller JavaScript payloads that load and become interactive faster — a factor in Core Web Vitals and search ranking.
Best Practices
Prefer Named Exports for Utility Modules, Default Exports for a Module's Single Main Value
Named exports are easier to refactor (renaming shows up as a clear error at every import site) and easier to tree-shake; reserve `export default` for files whose entire purpose is exposing one thing, like a single React component or class.
Avoid Circular Imports Between Modules
If module A imports from module B and B imports from A, one of the two will see an incomplete (partially initialized) version of the other's exports depending on load order — restructure shared logic into a third module that both A and B import from instead.
Frequent Bugs
Importing a named export using the wrong name, or importing a default export with curly braces, throws `SyntaxError: The requested module does not provide an export named 'X'`.
Named imports must match the exact name used after `export` in the source module; default exports are imported without braces (`import Thing from './file.js'`), while named exports require them (`import { thing } from './file.js'`).
A module-level `let` or `const` declared without `export` is undefined when another file tries to import it.
JavaScript modules have their own private scope by default — nothing is visible outside the file unless it's explicitly marked with `export`. Add `export` to the declaration, or add it to an `export { name }` statement at the bottom of the file.
Real-World Examples
Organizing a Small App into Feature Modules
A todo-list app kept growing past a single `app.js` file, mixing DOM manipulation, data storage, and formatting helpers together. Splitting it into `storage.js` (exports `saveTodos`/`loadTodos`), `format.js` (exports `formatDate`), and `app.js` (imports both and wires up the UI) made each piece independently testable.
// storage.js
export function saveTodos(todos) {
localStorage.setItem('todos', JSON.stringify(todos));
}
export function loadTodos() {
return JSON.parse(localStorage.getItem('todos') || '[]');
}
// app.js
import { saveTodos, loadTodos } from './storage.js';
const todos = loadTodos();