Lesson 13: Modules and Imports
What You'll Learn
- What modules are and why they matter
- How to export code from files
- How to import code into files
- Named vs default exports
- Organizing code into modules
- CommonJS vs ES Modules
Why This Matters
As programs grow, keeping all code in one file becomes unmaintainable. Modules let you split code into logical pieces, making it easier to organize, reuse, and maintain your codebase.
Part 1: What are Modules?
A module is a file that exports code (functions, classes, variables) that other files can import and use.
Benefits:- Organization: Related code stays together
- Reusability: Use same code in multiple places
- Maintainability: Easier to find and fix bugs
- Encapsulation: Hide implementation details
Part 2: ES Modules (Modern Way)
Modern Node.js and JavaScript use ES Modules.
Exporting from a Module
Create lesson-13/math.js:
// Named exports
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export const PI = 3.14159;
Importing from a Module
Create lesson-13/main.js:
// Import specific items
import { add, subtract, PI } from './math';
console.log(add(5, 3)); // 8
console.log(subtract(10, 4)); // 6
console.log(PI); // 3.14159
Import Everything
// Import all exports as a namespace
import * as Math from './math';
console.log(Math.add(5, 3)); // 8
console.log(Math.subtract(10, 4)); // 6
console.log(Math.PI); // 3.14159
Part 3: Default Exports
Each module can have ONE default export:
Create lesson-13/calculator.js:
// Default export
export default class Calculator {
add(a, b) {
return a + b;
}
subtract(a, b) {
return a - b;
}
multiply(a, b) {
return a * b;
}
divide(a, b) {
if (b === 0) throw new Error("Division by zero");
return a / b;
}
}
Import default export:
// No curly braces for default import
import Calculator from './calculator';
const calc = new Calculator();
console.log(calc.add(10, 5)); // 15
console.log(calc.multiply(4, 7)); // 28
Mixing Default and Named Exports
// utils.js
export default function greet(name) {
return `Hello, ${name}!`;
}
export function farewell(name) {
return `Goodbye, ${name}!`;
}
export const VERSION = "1.0.0";
// main.js
import greet, { farewell, VERSION } from './utils';
console.log(greet("Alice")); // Hello, Alice!
console.log(farewell("Bob")); // Goodbye, Bob!
console.log(VERSION); // 1.0.0
Part 4: Module Organization Patterns
Pattern 1: Feature-Based Structure
project/
├── users/
│ ├── user.js (User interface/class)
│ ├── userService.js (User business logic)
│ └── index.js (Export all)
├── products/
│ ├── product.js
│ ├── productService.js
│ └── index.js
└── main.js
users/user.js:
// User validation utilities
export class UserValidator {
static isValidEmail(email) {
return email.includes("@");
}
}
// Helper to create user objects
export function createUser(id, name, email) {
return { id, name, email };
}
users/userService.js:
import { UserValidator } from './user';
export class UserService {
constructor() {
this.users = [];
}
addUser(user) {
if (!UserValidator.isValidEmail(user.email)) {
throw new Error("Invalid email");
}
this.users.push(user);
}
getUsers() {
return this.users;
}
}
users/index.js:
// Re-export everything
export * from './user';
export * from './userService';
main.js:
// Import from the feature folder
import { createUser, UserService } from './users';
const service = new UserService();
service.addUser(createUser(1, "Alice", "alice@example.com"));
console.log(service.getUsers());
Part 5: Practical Example - Library System
book.js
// Helper to create book objects
export function createBook(isbn, title, author, year) {
return {
isbn,
title,
author,
year,
available: true
};
}
library.js
export class Library {
constructor() {
this.books = [];
}
addBook(book) {
this.books.push(book);
}
findByISBN(isbn) {
return this.books.find(b => b.isbn === isbn);
}
findByAuthor(author) {
return this.books.filter(b =>
b.author.toLowerCase().includes(author.toLowerCase())
);
}
borrowBook(isbn) {
const book = this.findByISBN(isbn);
if (book && book.available) {
book.available = false;
return true;
}
return false;
}
returnBook(isbn) {
const book = this.findByISBN(isbn);
if (book && !book.available) {
book.available = true;
return true;
}
return false;
}
listAvailableBooks() {
return this.books.filter(b => b.available);
}
}
main.js
import { Library } from './library';
import { createBook } from './book';
const library = new Library();
// Add books
library.addBook(createBook("978-0-123", "JavaScript Guide", "John Doe", 2023));
library.addBook(createBook("978-0-456", "Node.js Basics", "Jane Smith", 2022));
// List available
console.log("Available books:");
library.listAvailableBooks().forEach(book => {
console.log(`- ${book.title} by ${book.author}`);
});
// Borrow a book
library.borrowBook("978-0-123");
// List available again
console.log("\nAfter borrowing:");
library.listAvailableBooks().forEach(book => {
console.log(`- ${book.title}`);
});
Part 6: Configuration for ES Modules
To use ES modules in Node.js:
package.json
``json
{
"name": "lesson-13",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node main.js"
}
}
`
Note: The "type": "module"` is required to use ES modules (import/export) instead of CommonJS (require/module.exports).
Practice Exercises
Exercise 1: Math Library
Create a math library module with functions for:
- Basic operations (add, subtract, multiply, divide)
- Advanced operations (power, square root, factorial)
- Constants (PI, E)
Exercise 2: String Utilities
Create a string utilities module with functions like:
- capitalize, uppercase, lowercase
- reverse, isPalindrome
- wordCount, charCount
Exercise 3: Validator Module
Create a validation module with functions to validate:
- Email addresses
- Phone numbers
- URLs
- Credit card numbers (basic check)
Exercise 4: Shopping Cart
Organize a shopping cart application into modules:
- Product module
- Cart module
- Discount module
- Main application
Common Mistakes
Mistake 1: Circular Dependencies
// user.js
import { createPost } from './post';
export function createUser(name) {
return { name, posts: [] };
}
// post.js
import { createUser } from './user'; // ❌ Circular dependency!
export function createPost(author) {
return { author };
}
// Fix: Reorganize to avoid circular dependencies
Mistake 2: Forgetting File Extension
// ❌ Wrong (in some setups)
import { add } from './math';
// ✅ Correct
import { add } from './math.js'; // Note: .js even for .js files!
Mistake 3: Default Export Naming Confusion
// math.js
export default function calculate() { }
// main.js
import anything from './math'; // Works, but confusing
import calculate from './math'; // Better - matches export name
Key Concepts Summary
| Concept | Syntax | Purpose |
|---|---|---|
| Named Export | export function name() {} |
Export specific items |
| Default Export | export default class Name {} |
One main export per file |
| Named Import | import { name } from './file' |
Import specific items |
| Default Import | import Name from './file' |
Import default export |
| Namespace Import | import * as Name from './file' |
Import everything |
What You Learned
- ✅ How to export code from modules
- ✅ How to import code into files
- ✅ Difference between named and default exports
- ✅ How to organize code with modules
- ✅ Module patterns for scalable applications
- ✅ How to configure Node.js for ES modules
- ✅ Common module pitfalls to avoid
What's Next?
In the next lesson, you'll learn about Classes and Object-Oriented Programming - how to create blueprints for objects with properties and methods!