ES Modules Logo ESModules.com

Fundamentals

Master the core concepts of JavaScript ES Modules. Learn the export and import syntax, understand different export types, and build a strong foundation for modern JavaScript development.

What Are Modules?

Modules solve the problem of avoiding global scope pollution, organizing code, and enabling code reuse. Think of them as chapters in a book or LEGO bricks - self-contained pieces that work together.

Before ES Modules, JavaScript had no native module system. Developers relied on patterns like IIFE (Immediately Invoked Function Expressions) or tools like CommonJS and AMD. ES Modules provide a standardized, native way to organize and share code.

The Core Syntax: export

The export statement makes functions, objects, or values available to other modules.

Named Exports

Export multiple values from a module. Consumers must import them by name.

// math.js
export const PI = 3.14159;
export function add(a, b) {
  return a + b;
}
export function subtract(a, b) {
  return a - b;
}

Default Exports

Export a single main value from a module. Consumers can import it with any name.

// logger.js
export default function log(message) {
  console.log(`[LOG] ${message}`);
}

Renaming Exports

Export values under different names using the as keyword.

const myInternalVar = 42;
const helperFunction = () => {};

export {
  myInternalVar as publicValue,
  helperFunction as helper
};

Aggregating Exports

Re-export values from other modules (barrel pattern).

// index.js - barrel file
export { add, subtract } from './math.js';
export { default as Logger } from './logger.js';
export * from './utilities.js';

The Core Syntax: import

The import statement brings values from other modules into your code.

Importing Named Exports

Import specific values by name using curly braces.

import { PI, add } from './math.js';

console.log(PI); // 3.14159
console.log(add(5, 3)); // 8

Importing Default Export

Import the default export with any name you choose.

import log from './logger.js';

log('Application started');

Namespace Imports

Import all exports as a single object using the * as syntax.

import * as MathUtils from './math.js';

console.log(MathUtils.PI);
console.log(MathUtils.add(2, 3));

Renaming Imports

Import values under different names to avoid naming conflicts.

import { add as sum, subtract as diff } from './math.js';

console.log(sum(10, 5)); // 15
console.log(diff(10, 5)); // 5

Importing for Side Effects

Import a module just to run its code, without importing any values.

// Runs setup.js but doesn't import anything
import './setup.js';

Combining Default and Named Imports

Import both default and named exports in one statement.

import Logger, { LOG_LEVELS, formatMessage } from './logger.js';

const logger = new Logger();
logger.log(formatMessage('Hello', LOG_LEVELS.INFO));

Key Concepts

File Extensions Required

In browsers, you must include the .js extension in import paths.

// ❌ Wrong
import { utils } from './utils';

// ✅ Correct
import { utils } from './utils.js';

Strict Mode by Default

ES Modules automatically run in strict mode. No need for 'use strict'.

Deferred by Default

Module scripts are deferred automatically - they don't block HTML parsing and run after the document is loaded.

CORS Required

Modules are subject to CORS restrictions. Use a local development server, not file:// protocol.

Live Code Examples

See ES Modules running in real-time. Watch actual imports and exports execute with live console output. Want to edit the code? Click "Edit in CodePen" to experiment!

Live Examples

What You're Seeing

  • Real ES modules executing in your browser - not simulations
  • Live console output showing actual results
  • Switch examples to see different import/export patterns
  • Want to edit and experiment? Click "Edit in CodePen" above each example