Generated by GPT-5-mini| ES module | |
|---|---|
| Name | ES module |
| Type | Language feature |
| Introduced | 2015 |
| Standard | ECMAScript |
| File extensions | .js, .mjs |
| Operating system | Cross-platform |
ES module
ECMAScript modules provide a standardized module system for ECMAScript that enables declarative import and export of bindings across files and packages. Designed during the development of ECMAScript 6 and integrated into ECMAScript 2015, modules changed how Web browsers and Node.js handle code organization, dependency graphs, and execution semantics. They interact with many ecosystems and specifications, including WHATWG HTML, CommonJS, HTTP/1.1, and WebAssembly.
ES modules define a syntax and runtime semantics for modularizing JavaScript code using explicit import and export statements. The design replaces earlier ad hoc module patterns used by libraries such as RequireJS, Browserify, and AMD-based loaders, while aiming to interoperate with server-side ecosystems exemplified by Node.js and package registries like npm. Modules are executed in strict mode per ECMAScript specification and support static analysis opportunities leveraged by tools such as Webpack, Rollup, and esbuild.
The module proposal originated amid debates among contributors from organizations including Mozilla, Google, Microsoft, and Facebook. Formal specification work occurred in TC39 meetings leading to adoption in ECMAScript 2015. Subsequent iterations and clarifications were incorporated through ECMA International maintenance and editorial fixes. Browser vendors like Mozilla Corporation (via Firefox), Google LLC (via Chrome), Apple (via Safari), and the Node.js Foundation implemented loaders and runtime support, while standards groups such as WHATWG integrated module-related features into HTML Living Standard documents.
Module syntax uses top-level export and import declarations: named exports, default exports, and re-exports enable flexible API surfaces. Static structure permits compile-time analysis similar to transformations used by Babel, TypeScript, and Closure Compiler. Modules are implicitly strict, with lexical scoping rules aligned to ECMAScript function and block scoping. The module graph is a directed acyclic dependency graph typically built from module specifiers resolved per host-defined algorithms; execution follows a two-phase model: module instantiation then evaluation, which supports live bindings and temporal dead zone behavior observed in JavaScript let/const semantics.
Resolution of specifiers can be host-provided or algorithmic; browsers rely on URL and Fetch API semantics, while server runtimes apply file system heuristics and package manifest lookup such as package.json "exports" and "main" fields used by npm packages. Loader hooks allow customization: Node.js introduced --experimental-loader and resolver hooks to integrate custom loaders, and browser module maps were proposed to enable remapping. Build tools like Rollup and Parcel perform static resolution and tree-shaking by traversing the module graph, and HTTP/2 multiplexing, Service Workers, and Content Delivery Networks influence distribution and loader performance.
Interoperability mechanisms address differences between static ES module bindings and dynamic CommonJS require semantics used in Node.js and legacy modules authored for npm. Node.js implemented dual-mode support using file extensions (.mjs), package manifest flags ("type": "module"), and interop wrappers to emulate default export behavior and live bindings. Toolchains use transpilation and synthetic default exports to bridge semantics for bundlers like Webpack and transpilers like Babel and TypeScript. Edge cases include circular dependencies, synchronous require versus asynchronous module evaluation, and differences in top-level this and module scope as encountered in integrations with Electron and server-side frameworks.
Browsers accept