Docs

README

14.2 ES Modules Syntax

πŸ“– Introduction

ES Modules (ESM) provide a standardized, powerful syntax for organizing JavaScript code. This section covers every aspect of the import and export keywords, from basic usage to advanced patterns.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        ES MODULES SYNTAX OVERVIEW                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚     EXPORTING                              IMPORTING                        β”‚
β”‚     ─────────                              ─────────                        β”‚
β”‚                                                                             β”‚
β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚     β”‚  Named Export   β”‚ ◀──────────────▢  β”‚  Named Import   β”‚              β”‚
β”‚     β”‚  export { x }   β”‚                   β”‚  import { x }   β”‚              β”‚
β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚                                                                             β”‚
β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚     β”‚ Default Export  β”‚ ◀──────────────▢  β”‚ Default Import  β”‚              β”‚
β”‚     β”‚ export default  β”‚                   β”‚ import x from   β”‚              β”‚
β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚                                                                             β”‚
β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚     β”‚    Re-export    β”‚ ◀──────────────▢  β”‚ Namespace Importβ”‚              β”‚
β”‚     β”‚ export { } from β”‚                   β”‚ import * as     β”‚              β”‚
β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚                                                                             β”‚
β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚     β”‚                 β”‚                   β”‚ Dynamic Import  β”‚              β”‚
β”‚     β”‚                 β”‚ ◀──────────────▢  β”‚ import()        β”‚              β”‚
β”‚     β”‚                 β”‚                   β”‚ (returns Promise)β”‚              β”‚
β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎯 Learning Objectives

By the end of this section, you will:

  • β€’βœ… Master all export syntax variations
  • β€’βœ… Understand all import syntax patterns
  • β€’βœ… Use dynamic imports for code splitting
  • β€’βœ… Re-export and aggregate modules
  • β€’βœ… Handle circular dependencies
  • β€’βœ… Use top-level await

1️⃣ Named Exports

Basic Named Exports

// ═══════════════════════════════════════════════════════════════
// utils.js - Named exports
// ═══════════════════════════════════════════════════════════════

// Export at declaration
export const PI = 3.14159;
export const E = 2.71828;

export let counter = 0; // Can export let (live binding)

export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

export class Calculator {
  add(a, b) {
    return a + b;
  }
  subtract(a, b) {
    return a - b;
  }
}

// Export arrow function
export const multiply = (a, b) => a * b;

Export List (After Declaration)

// ═══════════════════════════════════════════════════════════════
// math.js - Export list pattern
// ═══════════════════════════════════════════════════════════════

// Declare first
const PI = 3.14159;
const E = 2.71828;

function add(a, b) {
  return a + b;
}

function subtract(a, b) {
  return a - b;
}

function internalHelper() {
  // This stays private (not exported)
  return "I'm internal!";
}

// Export at the end (preferred for readability)
export { PI, E, add, subtract };

// You can also rename while exporting
export { add as sum, subtract as difference };
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      NAMED EXPORTS                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   Two Styles:                                                       β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚   INLINE EXPORT         β”‚   β”‚   EXPORT LIST           β”‚        β”‚
β”‚   β”‚                         β”‚   β”‚                         β”‚        β”‚
β”‚   β”‚   export const x = 1;   β”‚   β”‚   const x = 1;          β”‚        β”‚
β”‚   β”‚   export function f()   β”‚   β”‚   function f() {...}    β”‚        β”‚
β”‚   β”‚   export class C        β”‚   β”‚   class C {...}         β”‚        β”‚
β”‚   β”‚                         β”‚   β”‚                         β”‚        β”‚
β”‚   β”‚   βœ“ Export immediately  β”‚   β”‚   export { x, f, C };   β”‚        β”‚
β”‚   β”‚   βœ“ Clear what's public β”‚   β”‚                         β”‚        β”‚
β”‚   β”‚                         β”‚   β”‚   βœ“ All exports visible β”‚        β”‚
β”‚   β”‚                         β”‚   β”‚   βœ“ Rename on export    β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                                                                     β”‚
β”‚   RENAMING:                                                         β”‚
β”‚                                                                     β”‚
β”‚   export { localName as exportedName };                             β”‚
β”‚                                                                     β”‚
β”‚   // Example                                                        β”‚
β”‚   const internalAdd = (a, b) => a + b;                              β”‚
β”‚   export { internalAdd as add };  // Exported as 'add'              β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2️⃣ Named Imports

// ═══════════════════════════════════════════════════════════════
// app.js - Named imports
// ═══════════════════════════════════════════════════════════════

// Basic named import
import { add, subtract } from './math.js';

// Import with alias (rename)
import { add as sum, subtract as minus } from './math.js';

// Import multiple
import { PI, E, add, subtract, Calculator } from './utils.js';

// Namespace import (import all as object)
import * as math from './math.js';
// Usage: math.add(), math.PI, etc.

// Mixed: You can combine patterns
import { add }, * as utils from './utils.js'; // ❌ Invalid!
// Instead, import separately or use namespace only
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      NAMED IMPORTS                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚   β”‚              IMPORT SYNTAX PATTERNS                      β”‚      β”‚
β”‚   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€      β”‚
β”‚   β”‚                                                          β”‚      β”‚
β”‚   β”‚  import { a, b, c } from './module.js';                  β”‚      β”‚
β”‚   β”‚           β–²  β–²  β–²                                        β”‚      β”‚
β”‚   β”‚           β”‚  β”‚  β”‚                                        β”‚      β”‚
β”‚   β”‚           └──┴──┴── Must match export names exactly      β”‚      β”‚
β”‚   β”‚                                                          β”‚      β”‚
β”‚   β”‚  import { a as x } from './module.js';                   β”‚      β”‚
β”‚   β”‚           β–²    β–²                                         β”‚      β”‚
β”‚   β”‚           β”‚    └── Local name (use 'x' in this file)     β”‚      β”‚
β”‚   β”‚           └─────── Original export name                  β”‚      β”‚
β”‚   β”‚                                                          β”‚      β”‚
β”‚   β”‚  import * as mod from './module.js';                     β”‚      β”‚
β”‚   β”‚          β–²                                               β”‚      β”‚
β”‚   β”‚          └── All exports as properties of 'mod'          β”‚      β”‚
β”‚   β”‚              mod.a, mod.b, mod.c, mod.default             β”‚      β”‚
β”‚   β”‚                                                          β”‚      β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                                                                     β”‚
β”‚   Common Mistakes:                                                  β”‚
β”‚                                                                     β”‚
β”‚   import { Add } from './math.js';  // ❌ Case sensitive!          β”‚
β”‚   import { add } from './math.js';  // βœ… Correct                  β”‚
β”‚                                                                     β”‚
β”‚   import { add } from 'math.js';    // ❌ Missing ./               β”‚
β”‚   import { add } from './math.js';  // βœ… Relative path           β”‚
β”‚                                                                     β”‚
β”‚   import { add } from './math';     // ⚠️  Might work (bundler)   β”‚
β”‚   import { add } from './math.js';  // βœ… Include extension        β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3️⃣ Default Exports

Exporting Default

// ═══════════════════════════════════════════════════════════════
// logger.js - Default export (ONE per module)
// ═══════════════════════════════════════════════════════════════

// Method 1: Export default class
export default class Logger {
    log(msg) {
        console.log(`[LOG]: ${msg}`);
    }
    error(msg) {
        console.error(`[ERROR]: ${msg}`);
    }
    warn(msg) {
        console.warn(`[WARN]: ${msg}`);
    }
}

// ═══════════════════════════════════════════════════════════════
// api.js - Default export function
// ═══════════════════════════════════════════════════════════════

export default function fetchData(url) {
    return fetch(url).then(r => r.json());
}

// ═══════════════════════════════════════════════════════════════
// config.js - Default export object
// ═══════════════════════════════════════════════════════════════

export default {
    apiUrl: 'https://api.example.com',
    timeout: 5000,
    retries: 3
};

// ═══════════════════════════════════════════════════════════════
// counter.js - Default export with named exports
// ═══════════════════════════════════════════════════════════════

let count = 0;

function increment() { return ++count; }
function decrement() { return --count; }
function getCount() { return count; }

// Named exports
export { increment, decrement };

// Default export
export default getCount;

Importing Default

// ═══════════════════════════════════════════════════════════════
// app.js - Importing default exports
// ═══════════════════════════════════════════════════════════════

// Import default - can use ANY name
import Logger from './logger.js'; // Class
import fetchData from './api.js'; // Function
import config from './config.js'; // Object
import getCount from './counter.js'; // Function

// You can name it anything (it's the DEFAULT)
import MyLogger from './logger.js'; // Same as Logger
import getData from './api.js'; // Same as fetchData
import settings from './config.js'; // Same as config

// Import default + named together
import getCount, { increment, decrement } from './counter.js';

// Alternative syntax for default
import { default as Logger } from './logger.js';
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    DEFAULT vs NAMED EXPORTS                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
β”‚   β”‚    DEFAULT EXPORT     β”‚    NAMED EXPORTS      β”‚                β”‚
β”‚   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€                β”‚
β”‚   β”‚                       β”‚                       β”‚                β”‚
β”‚   β”‚  ONE per module       β”‚  MANY per module      β”‚                β”‚
β”‚   β”‚                       β”‚                       β”‚                β”‚
β”‚   β”‚  export default x     β”‚  export { a, b, c }   β”‚                β”‚
β”‚   β”‚                       β”‚                       β”‚                β”‚
β”‚   β”‚  import X from        β”‚  import { a, b, c }   β”‚                β”‚
β”‚   β”‚  (any name)           β”‚  (exact names)        β”‚                β”‚
β”‚   β”‚                       β”‚                       β”‚                β”‚
β”‚   β”‚  No curly braces      β”‚  Curly braces         β”‚                β”‚
β”‚   β”‚                       β”‚  required             β”‚                β”‚
β”‚   β”‚                       β”‚                       β”‚                β”‚
β”‚   β”‚  Good for:            β”‚  Good for:            β”‚                β”‚
β”‚   β”‚  β€’ Main export        β”‚  β€’ Utility functions  β”‚                β”‚
β”‚   β”‚  β€’ Single class       β”‚  β€’ Constants          β”‚                β”‚
β”‚   β”‚  β€’ Config object      β”‚  β€’ Multiple exports   β”‚                β”‚
β”‚   β”‚                       β”‚                       β”‚                β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
β”‚                                                                     β”‚
β”‚   You CAN have both in the same module:                             β”‚
β”‚                                                                     β”‚
β”‚   // module.js                                                      β”‚
β”‚   export const helper = () => {};     // Named                      β”‚
β”‚   export const CONSTANT = 42;          // Named                     β”‚
β”‚   export default class Main {}         // Default                   β”‚
β”‚                                                                     β”‚
β”‚   // import.js                                                      β”‚
β”‚   import Main, { helper, CONSTANT } from './module.js';             β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

4️⃣ Re-exports (Aggregating Modules)

Creating a Barrel File (index.js)

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

// ═══════════════════════════════════════════════════════════════
// utils/string.js
// ═══════════════════════════════════════════════════════════════
export const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
export const lowercase = (str) => str.toLowerCase();

// ═══════════════════════════════════════════════════════════════
// utils/array.js
// ═══════════════════════════════════════════════════════════════
export const first = (arr) => arr[0];
export const last = (arr) => arr[arr.length - 1];
export default function shuffle(arr) {
  /* ... */
}

// ═══════════════════════════════════════════════════════════════
// utils/index.js - BARREL FILE (Re-exports everything)
// ═══════════════════════════════════════════════════════════════

// Re-export all from math
export * from './math.js';

// Re-export all from string
export * from './string.js';

// Re-export all named exports from array
export * from './array.js';

// Re-export default with a name
export { default as shuffle } from './array.js';

// You can also rename while re-exporting
export { add as sum, subtract as minus } from './math.js';

// Re-export specific items only
export { capitalize } from './string.js';
// ═══════════════════════════════════════════════════════════════
// app.js - Using the barrel file
// ═══════════════════════════════════════════════════════════════

// Instead of multiple imports:
// import { add, subtract } from './utils/math.js';
// import { capitalize } from './utils/string.js';
// import { first, last } from './utils/array.js';

// Single import from barrel:
import {
  add,
  subtract,
  capitalize,
  first,
  last,
  shuffle,
} from './utils/index.js';

// Or even simpler (if index.js is the default):
import { add, capitalize, first } from './utils';
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       BARREL FILES                                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   WITHOUT BARREL:                  WITH BARREL:                     β”‚
β”‚                                                                     β”‚
β”‚   utils/                           utils/                           β”‚
β”‚   β”œβ”€β”€ math.js                      β”œβ”€β”€ math.js                      β”‚
β”‚   β”œβ”€β”€ string.js                    β”œβ”€β”€ string.js                    β”‚
β”‚   └── array.js                     β”œβ”€β”€ array.js                     β”‚
β”‚                                    └── index.js  ← Barrel           β”‚
β”‚                                                                     β”‚
β”‚   // Multiple imports              // Single import                 β”‚
β”‚   import {a} from './utils/math'   import {                         β”‚
β”‚   import {b} from './utils/str'      a, b, c                        β”‚
β”‚   import {c} from './utils/arr'    } from './utils'                 β”‚
β”‚                                                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   RE-EXPORT SYNTAX:                                                 β”‚
β”‚                                                                     β”‚
β”‚   export * from './module.js';           // All named exports       β”‚
β”‚   export { a, b } from './module.js';    // Specific exports        β”‚
β”‚   export { a as x } from './module.js';  // Rename                  β”‚
β”‚   export { default } from './module.js'; // Re-export default       β”‚
β”‚   export { default as X } from './m.js'; // Default as named        β”‚
β”‚                                                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   ⚠️  CAUTION: Tree-shaking                                        β”‚
β”‚                                                                     β”‚
β”‚   Barrel files can hurt tree-shaking if:                            β”‚
β”‚   β€’ You import from barrel but only use 1 export                    β”‚
β”‚   β€’ Bundler can't eliminate unused code                             β”‚
β”‚                                                                     β”‚
β”‚   Solution: Direct imports for large modules                        β”‚
β”‚   import { specific } from './utils/specific.js'                    β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

5️⃣ Dynamic Imports

Lazy Loading with import()

// ═══════════════════════════════════════════════════════════════
// Dynamic import returns a Promise
// ═══════════════════════════════════════════════════════════════

// Basic dynamic import
async function loadModule() {
  const module = await import('./heavy-module.js');
  module.doSomething();
}

// Conditional loading
async function loadFeature(featureName) {
  if (featureName === 'charts') {
    const { Chart } = await import('./features/charts.js');
    return new Chart();
  } else if (featureName === 'maps') {
    const { Map } = await import('./features/maps.js');
    return new Map();
  }
}

// Load based on user action
document.getElementById('loadBtn').addEventListener('click', async () => {
  const { heavyFunction } = await import('./heavy-module.js');
  heavyFunction();
});

// Dynamic path (variable)
async function loadLocale(lang) {
  const translations = await import(`./locales/${lang}.js`);
  return translations.default;
}

// Error handling
async function safeLoad(modulePath) {
  try {
    const module = await import(modulePath);
    return module;
  } catch (error) {
    console.error(`Failed to load ${modulePath}:`, error);
    return null;
  }
}
// ═══════════════════════════════════════════════════════════════
// Real-world example: Route-based code splitting
// ═══════════════════════════════════════════════════════════════

const routes = {
  '/': () => import('./pages/Home.js'),
  '/about': () => import('./pages/About.js'),
  '/contact': () => import('./pages/Contact.js'),
  '/dashboard': () => import('./pages/Dashboard.js'),
};

async function navigate(path) {
  const loadPage = routes[path];

  if (loadPage) {
    const pageModule = await loadPage();
    const Page = pageModule.default;
    renderPage(new Page());
  } else {
    const { NotFound } = await import('./pages/NotFound.js');
    renderPage(new NotFound());
  }
}

// Listen for navigation
window.addEventListener('popstate', () => {
  navigate(window.location.pathname);
});
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      DYNAMIC IMPORTS                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   Static Import                    Dynamic Import                   β”‚
β”‚   ─────────────                    ──────────────                   β”‚
β”‚   import { x } from './m.js'       const m = await import('./m.js') β”‚
β”‚                                                                     β”‚
β”‚   β€’ Runs at parse time             β€’ Runs at runtime                β”‚
β”‚   β€’ Always loads                   β€’ Loads on demand                β”‚
β”‚   β€’ Top-level only                 β€’ Can use anywhere               β”‚
β”‚   β€’ Static path                    β€’ Variable path okay             β”‚
β”‚                                                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   USE CASES FOR DYNAMIC IMPORT:                                     β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚   β”‚  1. Code Splitting                                       β”‚      β”‚
β”‚   β”‚     Load features only when needed                       β”‚      β”‚
β”‚   β”‚     β†’ Reduces initial bundle size                        β”‚      β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚   β”‚  2. Conditional Loading                                  β”‚      β”‚
β”‚   β”‚     if (admin) { await import('./admin.js') }            β”‚      β”‚
β”‚   β”‚     β†’ Load based on user/environment                     β”‚      β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚   β”‚  3. Route-based Loading                                  β”‚      β”‚
β”‚   β”‚     Load page components on navigation                   β”‚      β”‚
β”‚   β”‚     β†’ SPA performance optimization                       β”‚      β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚   β”‚  4. Dynamic Module Paths                                 β”‚      β”‚
β”‚   β”‚     import(`./plugins/${name}.js`)                       β”‚      β”‚
β”‚   β”‚     β†’ Plugin systems, i18n                               β”‚      β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

6️⃣ Top-Level Await (ES2022)

// ═══════════════════════════════════════════════════════════════
// config.js - Top-level await in ES Modules
// ═══════════════════════════════════════════════════════════════

// You can use await at the top level of a module!

// Fetch config at module load
const response = await fetch('/api/config');
export const config = await response.json();

// Dynamic import at top level
const { default: lodash } = await import('lodash');
export const _ = lodash;

// Database connection
const db = await connectToDatabase();
export { db };

// Conditional initialization
export const cache = process.env.USE_CACHE ? await initCache() : null;
// ═══════════════════════════════════════════════════════════════
// app.js - Using module with top-level await
// ═══════════════════════════════════════════════════════════════

// This import waits for config.js to finish loading
import { config, db } from './config.js';

// config is already resolved!
console.log(config.apiUrl);

// db connection is ready
await db.query('SELECT * FROM users');
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      TOP-LEVEL AWAIT                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   BEFORE (ES2021 and earlier):        AFTER (ES2022+):             β”‚
β”‚                                                                     β”‚
β”‚   // Had to wrap in async IIFE       // Direct await!               β”‚
β”‚   let config;                         const config = await          β”‚
β”‚   (async () => {                        fetch('/config')            β”‚
β”‚     const res = await fetch(...)        .then(r => r.json());       β”‚
β”‚     config = await res.json();                                      β”‚
β”‚   })();                               export { config };            β”‚
β”‚                                                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   HOW IT WORKS:                                                     β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚   β”‚                                                       β”‚         β”‚
β”‚   β”‚    Module A (has top-level await)                     β”‚         β”‚
β”‚   β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚         β”‚
β”‚   β”‚    β”‚  const data = await fetch()  β”‚ ← Pauses here     β”‚         β”‚
β”‚   β”‚    β”‚  export { data }             β”‚                   β”‚         β”‚
β”‚   β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚         β”‚
β”‚   β”‚                      β”‚                                β”‚         β”‚
β”‚   β”‚                      β–Ό                                β”‚         β”‚
β”‚   β”‚    Module B (imports from A)                          β”‚         β”‚
β”‚   β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚         β”‚
β”‚   β”‚    β”‚  import { data } from './A'  β”‚ ← Waits for A     β”‚         β”‚
β”‚   β”‚    β”‚  console.log(data)           β”‚                   β”‚         β”‚
β”‚   β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚         β”‚
β”‚   β”‚                                                       β”‚         β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚                                                                     β”‚
β”‚   ⚠️  CAUTION: Can delay module loading                            β”‚
β”‚   β€’ Only use when necessary                                         β”‚
β”‚   β€’ Consider fallbacks for slow operations                          β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

7️⃣ Module Metadata

// ═══════════════════════════════════════════════════════════════
// import.meta - Module metadata object
// ═══════════════════════════════════════════════════════════════

// Get the URL of the current module
console.log(import.meta.url);
// "file:///home/user/project/src/module.js" (Node.js)
// "https://example.com/js/module.js" (Browser)

// Resolve relative paths
const imagePath = new URL('./image.png', import.meta.url);
console.log(imagePath.href);

// Check if this is the main module (Node.js)
if (import.meta.url === `file://${process.argv[1]}`) {
  console.log('This is the entry point!');
}

// In Node.js 20.6+, there's also:
// import.meta.dirname - Directory of current module
// import.meta.filename - Full path of current module

// Environment-specific metadata
console.log(import.meta.env); // Vite
console.log(import.meta.hot); // Hot Module Replacement

8️⃣ Circular Dependencies

// ═══════════════════════════════════════════════════════════════
// Circular dependencies: A imports B, B imports A
// ═══════════════════════════════════════════════════════════════

// ─── a.js ───
import { b } from './b.js';

export const a = 'A';

console.log('In a.js, b =', b); // Works because of live bindings

// ─── b.js ───
import { a } from './a.js';

export const b = 'B';

console.log('In b.js, a =', a); // Might be undefined!

// ═══════════════════════════════════════════════════════════════
// Solution 1: Function wrapping (lazy access)
// ═══════════════════════════════════════════════════════════════

// ─── a.js ───
import { getB } from './b.js';

export const a = 'A';
export const getA = () => a;

console.log('In a.js, b =', getB()); // Always works

// ─── b.js ───
import { getA } from './a.js';

export const b = 'B';
export const getB = () => b;

console.log('In b.js, a =', getA()); // Always works

// ═══════════════════════════════════════════════════════════════
// Solution 2: Restructure to avoid circular dependency
// ═══════════════════════════════════════════════════════════════

// ─── shared.js (new file) ───
export const shared = 'Shared value';

// ─── a.js ───
import { shared } from './shared.js';
export const a = shared + ' from A';

// ─── b.js ───
import { shared } from './shared.js';
export const b = shared + ' from B';
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    CIRCULAR DEPENDENCIES                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   PROBLEM:                          SOLUTIONS:                      β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”          1. Use function wrappers        β”‚
β”‚   β”‚  A  β”‚ ──────▢ β”‚  B  β”‚             (lazy evaluation)            β”‚
β”‚   β”‚     β”‚ ◀────── β”‚     β”‚                                          β”‚
β”‚   β””β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”˜          2. Restructure code             β”‚
β”‚                                       (extract shared code)         β”‚
β”‚   A imports B                                                       β”‚
β”‚   B imports A                       3. Merge modules                β”‚
β”‚   ⚠️  Risk of undefined!               (if tightly coupled)         β”‚
β”‚                                                                     β”‚
β”‚   WHY IT CAN FAIL:                                                  β”‚
β”‚                                                                     β”‚
β”‚   1. JS loads A.js                                                  β”‚
β”‚   2. A.js imports B.js β†’ pause A, load B                           β”‚
β”‚   3. B.js imports A.js β†’ A not finished! Gets partial exports      β”‚
β”‚   4. B.js finishes                                                  β”‚
β”‚   5. A.js continues                                                 β”‚
β”‚                                                                     β”‚
β”‚   Live bindings help (ESM exports are references, not copies)       β”‚
β”‚   but accessing before initialization still fails.                  β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

9️⃣ Best Practices Summary

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      ES MODULES BEST PRACTICES                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚   βœ… DO:                                                            β”‚
β”‚                                                                     β”‚
β”‚   β€’ Use named exports for utilities (easier refactoring)            β”‚
β”‚   β€’ Use default exports for main class/component per file           β”‚
β”‚   β€’ Include .js extension in imports (browser compatible)           β”‚
β”‚   β€’ Use barrel files for clean public APIs                          β”‚
β”‚   β€’ Use dynamic imports for large/optional features                 β”‚
β”‚   β€’ Keep modules focused (single responsibility)                    β”‚
β”‚                                                                     β”‚
β”‚   ❌ AVOID:                                                         β”‚
β”‚                                                                     β”‚
β”‚   β€’ Mixing default and many named exports (confusing)               β”‚
β”‚   β€’ Circular dependencies (restructure instead)                     β”‚
β”‚   β€’ Giant barrel files (tree-shaking issues)                        β”‚
β”‚   β€’ Mutating imported values (they're read-only bindings)          β”‚
β”‚   β€’ Side effects at module level (initialization issues)            β”‚
β”‚                                                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   FILE ORGANIZATION:                                                β”‚
β”‚                                                                     β”‚
β”‚   src/                                                              β”‚
β”‚   β”œβ”€β”€ components/                                                   β”‚
β”‚   β”‚   β”œβ”€β”€ Button.js          ← default export: class Button        β”‚
β”‚   β”‚   β”œβ”€β”€ Input.js           ← default export: class Input         β”‚
β”‚   β”‚   └── index.js           ← barrel: export { Button, Input }    β”‚
β”‚   β”œβ”€β”€ utils/                                                        β”‚
β”‚   β”‚   β”œβ”€β”€ math.js            ← named exports: add, subtract, etc   β”‚
β”‚   β”‚   β”œβ”€β”€ string.js          ← named exports: capitalize, trim     β”‚
β”‚   β”‚   └── index.js           ← barrel: export * from './...'       β”‚
β”‚   └── index.js               ← main entry point                    β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“š Summary

SyntaxPurposeExample
export const xNamed exportexport const PI = 3.14;
export { x, y }Export listexport { add, subtract };
export defaultDefault exportexport default class App {}
export { x as y }Rename exportexport { add as sum };
export * fromRe-export allexport * from './utils.js';
import { x }Named importimport { add } from './math.js';
import x fromDefault importimport App from './App.js';
import * as xNamespace importimport * as math from './math.js';
import()Dynamic importconst m = await import('./m.js');

πŸ“š Next Steps

Continue to 14.3 CommonJS & AMD to learn:

  • β€’Detailed CommonJS patterns
  • β€’AMD configuration with RequireJS
  • β€’Interoperability between systems
  • β€’Migration strategies
README - JavaScript Tutorial | DeepML