ES Modules
What Are ES Modules?
Section titled “What Are ES Modules?”ECMAScript Modules (ESM) are JavaScript’s built-in way to split your code into smaller, reusable files. Instead of writing everything in one large file, you create separate files for different features and connect them using import and export.
Why this matters:
- Code reuse: Write a function once, import it wherever you need it.
- Encapsulation: Variables and functions inside a module are private by default. Nothing leaks out unless you explicitly export it.
- Maintainability: Smaller, focused files are easier to understand, test, and update.
Setting Up Modules in the Browser
Section titled “Setting Up Modules in the Browser”To use ES modules in HTML, add type="module" to your script tag:
<script type="module" src="app.js"></script>A few things to keep in mind:
- Use a web server. Modules must be served over HTTP/HTTPS. Opening HTML files directly (
file://) won’t work due to browser security restrictions. - Include file extensions. Always write
'./formatters.js', not'./formatters'. The.jsextension is required. - Use relative paths. Start with
./or../to specify the path relative to the current file. - Modules load asynchronously. They behave like
<script defer>, so they won’t block page rendering.
Creating a Module
Section titled “Creating a Module”- Any JavaScript file becomes a module as soon as it uses
export. - There’s no special syntax to declare a file as a module. You just create a
.jsfile, write your code, and export what you want to share.
Exporting Module Members
Section titled “Exporting Module Members”To share code from a module, you need to export it. There are two ways to do this.
1. Named Exports
Section titled “1. Named Exports”Use named exports when a module shares multiple items. Add the export keyword before each variable or function:
// formatters.jsexport const capitalize = (text) => { return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();};
export const truncate = (text, maxLength) => { return text.length > maxLength ? text.slice(0, maxLength) + '...' : text;};2. Default Export
Section titled “2. Default Export”Use a default export when a module has one main thing to share. Each module can only have one default export:
// validator.jsexport default function isValidEmail(email) { const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailPattern.test(email);}3. Combining Both
Section titled “3. Combining Both”You can use named and default exports in the same file:
// productUtils.jsexport const TAX_RATE = 0.08; // named export
export const formatPrice = (price) => { // named export return `$${price.toFixed(2)}`;};
export default function calculateTotal(price, quantity) { // default export const subtotal = price * quantity; return subtotal + (subtotal * TAX_RATE);}Importing a Module
Section titled “Importing a Module”Once code is exported, you can import it into other files. The import syntax depends on how it was exported.
1. Importing Named Exports
Section titled “1. Importing Named Exports”Use curly braces {} with the exact names that were exported:
// app.jsimport { capitalize, truncate } from './formatters.js';
console.log(capitalize('hello world')); // "Hello world"console.log(truncate('This is a long text', 10)); // "This is a ..."2. Importing a Default Export
Section titled “2. Importing a Default Export”No curly braces needed. You can choose any name you like:
// app.jsimport isValidEmail from './validator.js';
console.log(isValidEmail('user@example.com')); // trueconsole.log(isValidEmail('invalid-email')); // false3. Importing Named and Default Together
Section titled “3. Importing Named and Default Together”When a module has both export types, import the default first, then named exports in curly braces:
// app.jsimport calculateTotal, { TAX_RATE, formatPrice } from './productUtils.js';4. Importing Everything
Section titled “4. Importing Everything”Use * as to group all exports from a module under one name:
// app.jsimport * as formatters from './formatters.js';
console.log(formatters.capitalize('hello')); // "Hello"console.log(formatters.truncate('Long text here', 5)); // "Long ..."