{
    "slug": "js_modules",
    "term": "ES Modules (import/export)",
    "category": "javascript",
    "difficulty": "beginner",
    "short": "The standard JavaScript module system — static imports/exports enable tree-shaking, top-level await, and strict mode by default.",
    "long": "ES Modules (ESM, ES2015) use import and export statements for static, lexically scoped module boundaries. Named exports: export function fn() {} — import { fn } from './mod.js'. Default exports: export default class Foo — import Foo from './mod.js'. Dynamic imports: const mod = await import('./mod.js') — lazy-loads a module, returns a Promise. Key properties: modules are singletons (imported once, cached), strict mode by default, top-level await supported, and static analysis enables tree-shaking (dead code elimination). Compared to CommonJS (require/module.exports): ESM is statically analysable and natively supported in browsers; CJS is dynamic and synchronous. Node.js supports both; use .mjs or \"type\": \"module\" in package.json for ESM.",
    "aliases": [
        "ES modules",
        "ESM",
        "import export JS",
        "JavaScript modules"
    ],
    "tags": [
        "javascript",
        "modules",
        "es6",
        "bundling"
    ],
    "misconception": "CommonJS (require) and ES modules (import) are interchangeable in modern Node.js. They have different semantics — CommonJS is synchronous and dynamic; ES modules are asynchronous, static, and support tree-shaking. Mixing them requires careful interop configuration and has edge cases around default exports.",
    "why_it_matters": "ES modules (import/export) provide static dependency analysis, tree-shaking, and proper scope isolation — replacing global script tags and CommonJS require() for browser code.",
    "common_mistakes": [
        "Mixing ES module import and CommonJS require() in the same file — causes runtime errors.",
        "Not using named exports for utility functions — default exports cannot be tree-shaken as effectively.",
        "Circular imports that cause undefined references at runtime — restructure to break the cycle.",
        "Dynamic import() not used for code-splitting — large bundles load everything even when unused."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "js_closures",
        "js_async_await"
    ],
    "prerequisites": [
        "js_bundling_concepts",
        "typescript_modules",
        "js_closures"
    ],
    "refs": [
        "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules"
    ],
    "bad_code": "// Global script pollution — all vars accessible everywhere:\n<script src=\"utils.js\"></script>  <!-- Adds Utils to window -->\n<script src=\"app.js\"></script>    <!-- Overwrites if same variable names -->\n\n// ES modules — scoped, explicit:\nimport { formatDate, formatCurrency } from './utils.js';\nexport function renderOrder(order) { /* ... */ }",
    "good_code": "// Named exports — import by name\n// math.js\nexport function add(a, b) { return a + b; }\nexport const PI = 3.14159;\n\n// main.js\nimport { add, PI } from './math.js';\nimport { add as sum } from './math.js'; // alias\n\n// Default export — one per file\n// logger.js\nexport default class Logger { log(msg) { console.log(msg); } }\n\n// main.js\nimport Logger from './logger.js'; // any name works\n\n// Dynamic import — code splitting / lazy loading\nconst button = document.querySelector('#load-chart');\nbutton.addEventListener('click', async () => {\n  const { Chart } = await import('./chart.js'); // loaded on demand\n  new Chart(document.querySelector('#canvas'));\n});",
    "quick_fix": "Use ES modules (import/export) in all new JavaScript — add type='module' to script tags or configure your bundler; avoid CommonJS require() in browser code as it prevents tree-shaking",
    "severity": "medium",
    "effort": "low",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/js_modules",
        "html_url": "https://codeclaritylab.com/glossary/js_modules",
        "json_url": "https://codeclaritylab.com/glossary/js_modules.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[ES Modules (import/export)](https://codeclaritylab.com/glossary/js_modules) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/js_modules"
            }
        }
    }
}