{
    "slug": "modules_esm",
    "term": "ES Modules (ESM)",
    "category": "javascript",
    "difficulty": "intermediate",
    "short": "The official JavaScript module system — import and export statements enable static dependency graphs, tree-shaking, and native browser module loading without a bundler.",
    "long": "ES Modules (ESM), standardised in ES2015, replaced the CommonJS require/module.exports pattern. Named exports (export const x = ...) and default exports (export default ...) are imported with import { x } from './mod.js' and import Foo from './mod.js' respectively. ESM is statically analysed — imports are resolved at parse time, not runtime, enabling bundlers to tree-shake unused exports. In browsers, <script type=\"module\"> loads ESM natively with automatic defer semantics and strict mode. In Node.js, ESM files use .mjs extension or \"type\": \"module\" in package.json. Key differences from CommonJS: ESM imports are live bindings (reflect mutations in the exporting module), CJS exports are copied values. Dynamic import() returns a Promise and enables code-splitting — loading a module on demand rather than at startup. Import maps (supported in modern browsers) allow remapping bare specifiers like 'react' to a CDN URL without a bundler.",
    "aliases": [
        "ES modules",
        "ESM",
        "import/export",
        "JavaScript modules",
        "native modules"
    ],
    "tags": [
        "javascript",
        "modules",
        "bundling",
        "tree-shaking",
        "esm",
        "browser"
    ],
    "misconception": "ESM imports are live bindings — if the exporting module later mutates an exported variable, the importing module sees the updated value. This is the opposite of CommonJS, which copies the value at require() time.",
    "why_it_matters": "ESM is the foundation of modern JavaScript tooling — tree-shaking, code splitting, and native browser loading all depend on ESM's static structure. Mixing CJS and ESM in Node.js projects is a frequent source of confusing errors.",
    "common_mistakes": [
        "Omitting the file extension in Node.js ESM imports — 'import x from './utils'' fails; the extension '.js' is required (no automatic resolution).",
        "Using require() in a .mjs file or a package with type:module — CJS and ESM cannot be mixed without dynamic import().",
        "Re-exporting a default as a named export — import Foo from './a'; export { Foo } is needed; export { default } from './a' is the cleaner form.",
        "Expecting top-level this to be the module object — in ESM, top-level this is undefined (strict mode), not the global or module object."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "async_await",
        "js_bundling_concepts",
        "js_import_maps",
        "js_top_level_await"
    ],
    "prerequisites": [
        "js_bundling_concepts",
        "js_top_level_await"
    ],
    "refs": [
        "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules",
        "https://nodejs.org/api/esm.html"
    ],
    "bad_code": "// CommonJS — no tree-shaking, runtime resolution:\nconst { format } = require('date-fns');\nmodule.exports = { formatDate };",
    "good_code": "// ESM — statically analysable, tree-shakeable:\nimport { format } from 'date-fns'; // bundler can drop unused date-fns exports\n\nexport function formatDate(date) {\n    return format(date, 'yyyy-MM-dd');\n}\n// In Node.js: file must be .mjs or package.json must have \"type\": \"module\"",
    "example_note": "The CJS version loads the entire date-fns library at runtime; the ESM version lets bundlers include only the format function. In the browser, <script type=\"module\"> defers automatically and scopes the module — no global pollution.",
    "quick_fix": "Add \"type\":\"module\" to package.json, rename .js to .mjs or update imports to include .js extensions",
    "severity": "low",
    "effort": "medium",
    "created": "2026-04-10",
    "updated": "2026-04-10",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/modules_esm",
        "html_url": "https://codeclaritylab.com/glossary/modules_esm",
        "json_url": "https://codeclaritylab.com/glossary/modules_esm.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 (ESM)](https://codeclaritylab.com/glossary/modules_esm) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/modules_esm"
            }
        }
    }
}