JS Modules
In this page:
export and import Basics
export marks a function, variable, or class as available for other files to use, and import brings that exported item into a different file so it can be used there too.
Note: Think of export as 'making something public' from a file, and import as 'requesting something public' from another file.
Warning: A value that isn't explicitly exported stays completely private to its own file, other modules simply cannot access it.
Example: export and import Basics
// math.js
export function add(a, b) { return a + b; }
// main.js
import { add } from './math.js';
console.log(add(2, 3));
Default Exports
A default export represents the single main thing a module provides, and is imported without curly braces, using any name the importing file chooses. A file can only have one default export, which is why it's typically used for a module's primary function, class, or component.
Note: A file can have at most one default export, reserve it for the primary thing that file is responsible for providing.
Warning: Because the importing file can name a default import anything it wants, inconsistent naming across a project can make code harder to follow.
Example: Default Exports
// user.js
export default function createUser(name) { return { name }; }
// main.js
import createUser from './user.js';
console.log(createUser("Sam"));
Named Exports
Named exports let a single file export multiple distinct values, each imported individually by its exact exported name, wrapped in curly braces on the importing side. A module can freely mix multiple named exports alongside a single default export.
Note: Named exports are ideal for utility files providing several related, independent functions that consumers might import selectively.
Warning: Named imports must exactly match the exported name, unless explicitly renamed with the as keyword during import.
Example: Named Exports
// utils.js
export const PI = 3.14;
export function double(n) { return n * 2; }
// main.js
import { PI, double } from './utils.js';
console.log(PI, double(5));
Using type="module" in a Script Tag
Adding type=module to a script tag tells the browser to treat that script as an ES module, enabling import and export syntax, and automatically deferring the script until after the page has parsed.
Note: Module scripts are automatically deferred, similar to the defer attribute, so you don't need to add defer separately on a module script.
Warning: Module scripts require the page to be served over http:// or https://, opening an HTML file directly from the file system typically blocks module imports.
Example: Using type="module" in a Script Tag
<script type="module">
import { add } from './math.js';
console.log(add(1, 2));
</script>
Module Scope
Every module has its own private top-level scope, meaning variables and functions declared in one module file are not automatically visible in another, unless they're explicitly exported and imported.
Note: Module scope naturally avoids polluting the global scope, a major advantage over older approaches that relied on multiple plain script tags sharing one global namespace.
Warning: Two modules can safely declare variables with the exact same name without any conflict, since each module's top-level scope is completely separate.
Example: Module Scope
// counter.js
let count = 0; // private to this module, not visible elsewhere
export function increment() { return ++count; }
- Forgetting to add type=module to the script tag, without it, export and import statements throw a syntax error.
- Mixing up default exports and named exports, their import syntax is different and cannot be used interchangeably.
- Trying to load a module directly from the local file system without a server, browsers block module imports over the file:// protocol for security reasons.
- export makes a function, variable, or class available to other files, and import brings it into another file that needs it.
- A default export is the main thing a module provides, while named exports allow multiple distinct exports from one file.
- Adding type=module to a script tag is required to use import and export, and modules automatically run in their own private scope.
Native ES modules with type=module have been supported in all major browsers since around 2018 and are now a fully standard part of the web platform.
Chapter Quiz — Complete all 26 topics to unlock
0/26 topics done
Complete these topics first:
- JS Dates
- JS Math
- JS Conditionals
- JS Switch
- JS Loop For
- JS Loop While
- JS Iterables
- JS Sets
- JS Maps
- JS typeof
- JS Type Conversion
- JS Destructuring
- JS Arrow Functions
- JS Classes
- JS Modules
- JS Promises
- JS Async/Await
- JS DOM
- JS DOM Methods
- JS Events Advanced
- JS DOM Navigation
- JS DOM Collections
- JS Async Callbacks
- JS Async Parallel
- JS Date Set
- JS Set Logic