Modules & Bundling
ES Modules — import & export
Master modern ECMAScript Modules (ESM) in JavaScript. Learn static imports, exports syntax, browser module integration, and runtime compilation rules.
1. Introduction
ES Modules (ESM) is the official, standardized module system for JavaScript. It manages modules using the import and export keywords, enabling static analysis and native module loading directly in web browsers.
2. Why It Matters
ES Modules are parsed statically before code execution. This design allows bundlers to perform optimizations like Tree Shaking (removing unused code) and allows browsers to load modules in parallel, improving performance.
3. Real-World Analogy
Think of a Customs Declaration System:
- CommonJS (Packed trunk): You bring a sealed shipping crate into a country. Customs must open and scan the entire crate (run the module code) to find what is inside before they can approve it.
- ES Modules (Declared cargo manifesto): You attach a clear cargo manifest list showing exactly what is exported and imported (static declarations) to the outside of the container. Customs reads the manifest and routes the container immediately, without needing to open it first (enabling static analysis and optimization).
4. ES Modules Syntax
Unlike CommonJS, ES Modules use explicit export statements to share functions, classes, or values:
5. ES Modules in the Browser
To run ES Modules natively in web browsers, load script tags using the type="module" attribute:
Characteristics of script modules in browsers:
• Strict Mode: Script modules automatically run in strict mode (no need to specify "use strict").
• CORS Requirements: Modules are loaded using CORS, requiring server responses to include correct headers.
• Deferred Load: Script modules are deferred by default, loading in parallel and executing only after the DOM has finished parsing.
6. Practical Example
This script demonstrates importing all exports from a module into a namespace object:
7. Common Mistakes
- Omitting file extensions in relative imports: Modern bundlers (like Webpack) resolve files without extensions automatically, but native browser modules and Node.js ESM require relative imports to specify file extensions explicitly:
import { add } from './math.js'.
8. Quick Quiz
Q1: Which attribute is required on script tags to run ES Modules natively in the browser?
A) type="javascript"
B) type="module"
Answer: B — The type="module" attribute tells the browser to parse the script tag as an ES Module.
9. Scenario-Based Challenge
The Multi-Library Scope Conflict Resolver:
An application imports two separate math modules: math-lib.js and physics-math.js. Both modules export a function named calculate(). Write the import statement that renames (aliases) these functions during import to resolve the name conflict.
10. Debugging Exercise
Explain why this native browser script tag fails to execute during page load:
<!-- HTML -->
<script type="module">
// Objective: import calculation helpers
import { add } from './math'; // throws error! Why?
</script>
View Solution
Diagnosis: Native browser ES Modules do not support automatic file resolution. Relative import paths must specify file extensions explicitly.
Fix: Add the .js file extension to the import path:
import { add } from './math.js'; // Specifies extension
11. Interview Questions
🟢 Q1: Compare ES Modules (ESM) and CommonJS (CJS) in terms of loading timing and optimizations.
Answer:
• CommonJS: Loads modules synchronously. The module code runs during the require call, exporting a copied reference. Because exports are determined dynamically at runtime, bundlers cannot optimize code structure easily.
• ES Modules: parsed statically before code execution. Imports and exports are resolved before the code runs, creating live bindings to the exported values. This design allows bundlers to analyze dependency chains statically and perform optimizations like tree shaking.
12. Production Considerations
- • CORS Headers: When serving ES Modules natively in production, configure the hosting server to include correct CORS headers (like
Access-Control-Allow-Origin). Browsers fetch modules using CORS, and missing headers will cause module loads to fail.