Important Differences From Regular Scripts

ES Modules have several key behaviors that distinguish them from ordinary <script> tags.

1. Their Own Scope

Variables declared in one module are NOT visible in others unless explicitly exported. Each module is a private scope.

// counter.js
let count = 0; // only accessible within counter.js
export function increment() { count++; }
export function getCount() { return count; }

2. Code Runs Only Once

No matter how many files import the same module, the module's code executes exactly once on the first import. All importers share the same cached instance.

// logger.js
console.log('Logger module loaded'); // Only logs ONCE, even if imported by 10 files

export function log(msg) { console.log('[LOG]', msg); }

3. import.meta

An object containing metadata about the current module:

console.log(import.meta.url); // Full URL of the current module file

4. Default Exports

Use export default when a module exports one primary thing. On import, you don't need curly braces:

// UserCard.js
export default class UserCard { ... }

// main.js
import UserCard from './UserCard.js'; // No curly braces!
Tip

Use export default for the " main " export of a module (like a React component). Use named exports (export { fn }) for utilities and secondary exports.