JS Modules Best Practices
Organize code into reusable, maintainable modules.
import/exportstructuremaintainabilityTable of Contents
JavaScript Modules Tutorial
JavaScript modules allow you to split your code into separate files, making it more organized, reusable, and maintainable. ES6 modules are natively supported in all modern browsers.

import and export patterns.What Are JavaScript Modules?
Modules are discrete JavaScript files that can export functions, objects, or values for use in other files, and import functionality from other modules. Think of modules as building blocks where each file contains one focused piece of functionality.
Why Use Modules?
- Encapsulation: Each module has its own scope.
- Reusability: Write once, use in multiple files.
- Maintainability: Easier debugging and updates in isolated units.
- Dependency management: Clear relationships between files.
Setting Up Modules
Use type="module" in your script tag.
<script type="module" src="main.js"></script>
<script type="module">
// Module code here
</script>Important: Modules are deferred by default and should run over HTTP(s), not file://. Use a local server for testing.
Exporting Code from Modules
1. Individual (Inline) Exports
// math.js
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export class Calculator { multiply(a, b) { return a * b; } }2. Unified Exports
// math.js
const PI = 3.14159;
function add(a, b) { return a + b; }
class Calculator { multiply(a, b) { return a * b; } }
export { PI, add, Calculator };3. Default Exports
// utils.js
export default function formatCurrency(amount) {
return `$${amount.toFixed(2)}`;
}Importing Code into Modules
Import Named Exports
import { PI, add } from "./math.js";
import { add as sum, Calculator as Calc } from "./math.js";Import Default Exports
import formatMoney from "./utils.js";Import Everything (Namespace)
import * as mathUtils from "./math.js";
console.log(mathUtils.add(5, 3));Combine Named + Default
import greet, { version } from "./my-module.js";Dynamic Imports
Load heavy modules only when needed for performance.
button.addEventListener("click", async () => {
const module = await import("./heavy-module.js");
module.doSomething();
});Working Example: A Shopping Cart Module System
Project Structure
cart-app/
├── index.html
├── main.js
└── modules/
├── products.js
├── cart.js
└── utils.jsStep 1: products.js
const products = [
{ id: 1, name: "JavaScript Book", price: 29.99 },
{ id: 2, name: "Coffee Mug", price: 12.99 },
{ id: 3, name: "Hoodie", price: 49.99 }
];
export function getProduct(id) { return products.find(p => p.id === id); }
export function getAllProducts() { return [...products]; }
export default products;Step 2: utils.js
export function formatPrice(amount) { return `$${amount.toFixed(2)}`; }
export function calculateDiscount(price, percentage) {
return price - (price * percentage / 100);
}Step 3: cart.js
import products from "./products.js";
let cartItems = [];
export function addToCart(productId, quantity = 1) {
const product = products.find(p => p.id === productId);
if (!product) return false;
const existing = cartItems.find(item => item.id === productId);
if (existing) existing.quantity += quantity;
else cartItems.push({ ...product, quantity });
return true;
}
export function getCartTotal() {
return cartItems.reduce((sum, item) => sum + item.price * item.quantity, 0);
}Step 4: main.js
import { getAllProducts } from "./modules/products.js";
import { addToCart, getCartTotal, getCartCount, getCartItems } from "./modules/cart.js";
import { formatPrice } from "./modules/utils.js";
window.addToCartHandler = productId => {
addToCart(productId);
updateCartDisplay();
};Step 5: index.html
<!DOCTYPE html>
<html>
<head><title>Shopping Cart</title></head>
<body>
<h2>Products</h2>
<div id="products"></div>
<h2>Cart (<span id="cart-count">0</span>)</h2>
<div id="cart"></div>
<h3>Total: <span id="cart-total">$0.00</span></h3>
<script type="module" src="main.js"></script>
</body>
</html>Important Notes
File Extensions
import { add } from "./math.js"; // Correct
// import { add } from "./math"; // Fails in native browser ESMModule Scope
// secret.js
const secretKey = "abc123";
export function getSecret() { return secretKey; }Node.js
In Node.js, enable ES modules with "type": "module" in package.json or by using .mjs files.
Common Mistakes to Avoid
- Forgetting
type="module"in script tags. - Using wrong relative paths (use
./when needed). - Missing
.jsextension in native browser imports. - Creating circular dependencies between modules.
- Running modules directly from
file://instead of a local server.
Related: ES6 Features, Async JavaScript.