ES Modules

Loading concept...

🚀 ES Modules: JavaScript’s Modern Shipping System

The Big Picture: What Are ES Modules?

Imagine you’re building a LEGO castle. Instead of having ALL the pieces dumped in one giant pile, what if you had labeled boxes?

  • 📦 Box 1: Castle walls
  • 📦 Box 2: Towers
  • 📦 Box 3: Knights

That’s exactly what ES Modules do for your code!

ES Modules (ESM) = JavaScript’s official way to organize code into separate, reusable files that can share parts with each other.


🏠 Our Analogy: The Neighborhood Library

Think of your JavaScript project as a neighborhood. Each house (file) has books (functions, variables) they can share with neighbors.

  • export = Putting a book on your front porch for neighbors
  • import = Borrowing a book from a neighbor’s porch

Let’s explore this neighborhood!


📖 1. ES Modules Overview

What Problem Do They Solve?

Before modules, all JavaScript lived in ONE file. Imagine a library with all books in one giant pile. Chaos!

// ❌ OLD WAY: Everything in one file
function add(a, b) { return a + b; }
function subtract(a, b) { return a - b; }
function multiply(a, b) { return a * b; }
// ...500 more functions...
// 😵 Where is anything?!

The ES Modules Solution

// ✅ NEW WAY: Organized files
// math.js - just math stuff
export function add(a, b) {
  return a + b;
}

// app.js - uses math
import { add } from './math.js';
console.log(add(2, 3)); // 5

How to Enable ES Modules in Node.js

Two ways to tell Node.js “I’m using modules!”:

Way 1: Use .mjs extension

my-file.mjs  ← Node knows this is a module

Way 2: Add to package.json

{
  "type": "module"
}

Now ALL .js files in that folder are modules!


📤📥 2. Import and Export Syntax

Named Exports: Sharing Specific Books

Like putting specific books on your porch with labels:

// library.js
export const bookTitle = "Harry Potter";
export function readBook() {
  return "Reading...";
}
export class Library {
  constructor() {
    this.books = [];
  }
}

Named Imports: Borrowing by Name

// reader.js
import {
  bookTitle,
  readBook,
  Library
} from './library.js';

console.log(bookTitle);  // "Harry Potter"
readBook();              // "Reading..."

Default Export: The “Star” of the File

Each file can have ONE special “main thing”:

// superhero.js
export default function fly() {
  return "Whoooosh! 🦸";
}
// app.js
import fly from './superhero.js';
// No curly braces needed!
// You can even rename it:
import soar from './superhero.js';

Renaming with as

// Avoid name conflicts!
import { add as mathAdd } from './math.js';
import { add as stringAdd } from './strings.js';

Import Everything: The * as Pattern

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

MathUtils.add(1, 2);
MathUtils.subtract(5, 3);

Quick Reference Table

What You Want Syntax
Export one thing export const x = 5
Export main thing export default fn
Import named import { x } from './file.js'
Import default import x from './file.js'
Import all import * as X from './file.js'
Rename import { x as y } from './file.js'

⚡ 3. Dynamic Imports

The Problem with Regular Imports

Regular imports load immediately when your app starts:

import { heavyChart } from './charts.js';
// Loads even if user never sees charts!

Dynamic Import: Load When Needed!

Like ordering a pizza only when hungry:

// Only load charts when user clicks button
async function showCharts() {
  const { heavyChart } = await import('./charts.js');
  heavyChart.render();
}

How It Works

graph TD A[App Starts] --> B[User Clicks Button] B --> C[import runs] C --> D[Module Downloads] D --> E[Code Executes]

Real Example: Lazy Loading

button.addEventListener('click', async () => {
  // Module loads ONLY when clicked
  const module = await import('./heavy-feature.js');
  module.init();
});

Dynamic Import Returns a Promise

import('./math.js')
  .then(module => {
    console.log(module.add(2, 3));
  })
  .catch(err => {
    console.log('Failed to load!');
  });

🔍 4. The import.meta Object

What Is It?

import.meta is like a name tag that tells you about the current module.

import.meta.url

The most useful property! Tells you WHERE this file is:

// /home/user/project/utils.js
console.log(import.meta.url);
// Output: "file:///home/user/project/utils.js"

Real Use Case: Find Files Near Your Module

import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';

// Get directory of current file
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Read file next to this module
const data = readFileSync(
  join(__dirname, 'config.json')
);

Why Do We Need This?

In CommonJS, we had __dirname built-in. In ES Modules, we use import.meta.url instead!

// CommonJS (old)
console.log(__dirname); // Just works

// ES Modules (new)
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(
  fileURLToPath(import.meta.url)
);

⚔️ 5. ESM vs CommonJS Differences

The Two Module Systems

Feature CommonJS ES Modules
Syntax require() import
Export module.exports export
File ext .js or .cjs .mjs or .js
Loading Synchronous Asynchronous
Top-level await ❌ No ✅ Yes

Side-by-Side Comparison

CommonJS:

// math.js
const add = (a, b) => a + b;
module.exports = { add };

// app.js
const { add } = require('./math.js');

ES Modules:

// math.js
export const add = (a, b) => a + b;

// app.js
import { add } from './math.js';

Can They Talk to Each Other?

graph LR A[ESM File] -->|Can import| B[CommonJS] B -->|Cannot require| A

ESM can import CommonJS:

// In an ESM file
import pkg from './commonjs-file.cjs';

CommonJS CANNOT require ESM directly!

// ❌ This will fail!
const module = require('./esm-file.mjs');

Key Difference: require() vs import

// CommonJS: require can be anywhere
if (needMath) {
  const math = require('./math.js'); // ✅ OK
}

// ESM: import must be at top
import { add } from './math.js';
// Cannot put import inside if-statement!
// Use dynamic import() instead

🎯 6. ESM Hoisting Behavior

What Is Hoisting?

Hoisting = JavaScript moves things to the top before running.

Imports Are ALWAYS Hoisted

No matter WHERE you write import, it runs FIRST:

console.log("Step 1");

import { greet } from './hello.js';
// ⬆️ This actually runs BEFORE "Step 1"!

console.log("Step 2");
greet();

What Actually Happens:

// JavaScript reorganizes to:
import { greet } from './hello.js'; // FIRST!
console.log("Step 1");              // Second
console.log("Step 2");              // Third
greet();                            // Fourth

Why Does This Matter?

You can use imports anywhere in your code:

// This works! greet exists because
// import hoisted to top
greet();

import { greet } from './hello.js';

But Wait… There’s More!

Imported values are live bindings:

// counter.js
export let count = 0;
export function increment() {
  count++;
}

// app.js
import { count, increment } from './counter.js';
console.log(count); // 0
increment();
console.log(count); // 1 ← Updated!

The count variable updates automatically!

Hoisting vs. Dynamic Import

Type Hoisted? When Loaded?
import x from ✅ Yes Before any code
import() ❌ No When that line runs

🎓 Recap: Your ES Modules Cheat Code

graph TD A[ES Modules] --> B[export/import] A --> C[Dynamic import] A --> D[import.meta] B --> E[Named: export const x] B --> F[Default: export default] C --> G[Lazy loading] D --> H[import.meta.url]

🏆 You Now Know:

  1. ES Modules overview - Organize code into files
  2. import/export syntax - Share code between files
  3. Dynamic imports - Load code when needed
  4. import.meta - Get info about current file
  5. ESM vs CommonJS - Modern vs legacy systems
  6. Hoisting - Imports always run first

🚀 One Last Tip

Think of ES Modules as your code’s postal system:

  • 📦 export = Package and label your code
  • 📬 import = Receive packages from other files
  • 🚚 import() = Special delivery (when you need it)
  • 🏷️ import.meta = Return address on the package

Now go build something amazing with your organized, modular JavaScript! 🎉

Loading story...

No Story Available

This concept doesn't have a story yet.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive Preview

Interactive - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Interactive Content

This concept doesn't have interactive content yet.

Cheatsheet Preview

Cheatsheet - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Cheatsheet Available

This concept doesn't have a cheatsheet yet.

Quiz Preview

Quiz - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Quiz Available

This concept doesn't have a quiz yet.