ES6 modules are a way to organize and structure JavaScript code by dividing it into reusable pieces. Introduced in ES6 (ECMAScript 2015), modules allow developers to define code in separate files and explicitly export or import only the parts needed. This improves maintainability, reusability, and scalability in projects.
Key Concepts of ES6 Modules
Named Exports and Imports
A module can export multiple values by name.
math.js (Module)
export const add = (a, b) => a + b; export const subtract = (a, b) => a - b; export const multiply = (a, b) => a * b;
main.js (Importing Module)
import { add, subtract } from './math.js'; console.log(add(2, 3)); // 5 console.log(subtract(5, 2)); // 3
You can also rename imports:
import { add as addition } from './math.js'; console.log(addition(3, 4)); // 7
Default Exports and Imports
A module can export one default value. This is often used when the module is exporting a single functionality or object.
utils.js (Module)
export default function greet(name) { return `Hello, ${name}!`; }
main.js (Importing Module)
import greet from './utils.js'; console.log(greet('Alice')); // Hello, Alice!
Default imports can have any name:
import welcome from './utils.js'; console.log(welcome('Bob')); // Hello, Bob!
Combining Named and Default Exports
You can mix named and default exports in the same file.
shapes.js (Module)
export const PI = 3.14159; export function areaOfCircle(radius) { return PI * radius * radius; } export default class Circle { constructor(radius) { this.radius = radius; } getArea() { return areaOfCircle(this.radius); } }
main.js (Importing Module)
import Circle, { PI, areaOfCircle } from './shapes.js'; const myCircle = new Circle(5); console.log(myCircle.getArea()); // 78.53975 console.log(PI); // 3.14159 console.log(areaOfCircle(3)); // 28.274309999999996
Re-exporting Modules
Modules can re-export items from another module, which is useful for creating a central "index" file.
math.js
export const add = (a, b) => a + b; export const subtract = (a, b) => a - b;
index.js
export { add, subtract } from './math.js';
main.js
import { add } from './index.js'; console.log(add(4, 7)); // 11
Dynamic Imports
Dynamic imports allow you to load modules dynamically at runtime using import(). This is useful for code-splitting and lazy loading.
logger.js
export default function logMessage(message) { console.log(`Log: ${message}`); }
main.js
if (someCondition) { import('./logger.js').then(({ default: logMessage }) => { logMessage('Dynamic import works!'); }); }
ES6 Module Syntax in Browsers
To use ES6 modules in a browser, ensure your script has the type="module" attribute:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ES6 Modules</title> </head> <body> <script type="module" src="main.js"></script> </body> </html>
ES6 modules provide a clean, standardized way to organize and share code in JavaScript, enabling better collaboration and modularity in projects.