🔥 0
0
Lesson 3 of 10 12 min +60 XP

Modules & require

As your code grows, you need to split it into files. Modules let you organize code and share functionality between files.

Why Modules?

Imagine a 5,000-line file with everything mixed together:

// nightmare.js - Don't do this!
// Database connection code...
// User authentication...
// Email sending...
// API routes...
// Utility functions...
// More chaos...

With modules, you organize by responsibility:

/project
  /src
    database.js    // Database logic
    auth.js        // Authentication
    email.js       // Email utilities
    utils.js       // Helper functions
    app.js         // Main entry point

Creating a Module

Create a file called math.js:

// math.js
function add(a, b) {
  return a + b;
}

function subtract(a, b) {
  return a - b;
}

function multiply(a, b) {
  return a * b;
}

// Export what you want others to use
module.exports = {
  add,
  subtract,
  multiply
};

Using a Module

Create app.js in the same folder:

// app.js
const math = require('./math');

console.log(math.add(5, 3));        // 8
console.log(math.subtract(10, 4));  // 6
console.log(math.multiply(3, 7));   // 21
Run it:
node app.js
Output:
8
6
21

The require Path Matters

// Local files - use relative paths (start with . or ..)
const math = require('./math');           // same folder
const utils = require('./lib/utils');     // subfolder
const config = require('../config');      // parent folder

// npm packages - just the name (no ./)
const express = require('express');
const lodash = require('lodash');

// Built-in modules - just the name
const fs = require('fs');
const path = require('path');
Common mistake:
// WRONG - Node thinks 'math' is an npm package
const math = require('math');

// CORRECT - ./ tells Node it's a local file
const math = require('./math');

Different Export Styles

Style 1: Export an object
// utils.js
module.exports = {
  formatDate: (date) => date.toISOString(),
  capitalize: (str) => str.charAt(0).toUpperCase() + str.slice(1)
};

// usage
const utils = require('./utils');
utils.formatDate(new Date());
utils.capitalize('hello');
Style 2: Export a single function
// logger.js
module.exports = function log(message) {
  console.log(`[${new Date().toISOString()}] ${message}`);
};

// usage
const log = require('./logger');
log('Server started');
Style 3: Export a class
// User.js
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  greet() {
    return `Hello, I'm ${this.name}`;
  }
}

module.exports = User;

// usage
const User = require('./User');
const alice = new User('Alice', 'alice@example.com');
console.log(alice.greet());

Destructuring Imports

If you only need specific exports:

// Instead of this:
const math = require('./math');
const result = math.add(1, 2);

// You can do this:
const { add, multiply } = require('./math');
const result = add(1, 2);

Built-in Modules

Node.js comes with useful modules built-in:

// File system
const fs = require('fs');

// Path utilities
const path = require('path');

// Operating system info
const os = require('os');

// HTTP server/client
const http = require('http');

// Cryptography
const crypto = require('crypto');

Quick example with path:

// path-demo.js
const path = require('path');

const filePath = '/users/alice/documents/report.pdf';

console.log(path.basename(filePath));  // report.pdf
console.log(path.dirname(filePath));   // /users/alice/documents
console.log(path.extname(filePath));   // .pdf

// Join paths safely (handles / automatically)
const newPath = path.join('users', 'bob', 'file.txt');
console.log(newPath);  // users/bob/file.txt

Try It Yourself

Create a mini project with multiple modules:

strings.js:
// strings.js
module.exports = {
  reverse: (str) => str.split('').reverse().join(''),
  isPalindrome: (str) => {
    const clean = str.toLowerCase().replace(/[^a-z]/g, '');
    return clean === clean.split('').reverse().join('');
  }
};
numbers.js:
// numbers.js
module.exports = {
  isEven: (n) => n % 2 === 0,
  factorial: (n) => n <= 1 ? 1 : n * factorial(n - 1)
};
main.js:
// main.js
const strings = require('./strings');
const numbers = require('./numbers');

console.log(strings.reverse('hello'));        // olleh
console.log(strings.isPalindrome('racecar')); // true
console.log(numbers.isEven(4));               // true
console.log(numbers.factorial(5));            // 120
Run it:
node main.js

ES Modules (Quick Note)

Node.js also supports the newer import/export syntax:

// math.mjs (note .mjs extension)
export function add(a, b) {
  return a + b;
}

// app.mjs
import { add } from './math.mjs';
console.log(add(1, 2));

For now, we'll use require() (CommonJS) as it's still the most common in Node.js tutorials and existing code.

Key Takeaways

  • Modules split code into organized files
  • module.exports defines what a file shares
  • require('./file') imports local files (note the ./)
  • require('package') imports npm packages
  • Built-in modules like fs, path, http come with Node.js

Next, let's explore npm and the world of packages!

🧠 Quick Quiz

Test your understanding of this lesson.

1

What does module.exports do?

2

How do you import a local file called utils.js?

3

What's the difference between module.exports and exports?

Your First Node Script