CommonJS and Module Systems
Learning Objectives
- By the end of this lesson, you will be able to:
- - Understand CommonJS module system
- - Use `require()` and `module.exports`
- - Understand AMD modules
- - Learn about module bundlers (Webpack, Rollup)
- - Compare different module systems
- - Choose the right module system for your project
- - Understand module loading strategies
Lesson 11.2: CommonJS and Module Systems
Learning Objectives
By the end of this lesson, you will be able to:
- Understand CommonJS module system
- Use
require()andmodule.exports - Understand AMD modules
- Learn about module bundlers (Webpack, Rollup)
- Compare different module systems
- Choose the right module system for your project
- Understand module loading strategies
Introduction to Module Systems
JavaScript has evolved through different module systems. Understanding them helps you work with different codebases and tools.
Module System Evolution
- No Modules: Global variables (old way)
- CommonJS: Node.js standard (require/module.exports)
- AMD: Asynchronous Module Definition (browser)
- ES6 Modules: Modern standard (import/export)
- Bundlers: Tools that combine modules (Webpack, Rollup)
CommonJS
CommonJS is the module system used in Node.js. It uses require() to import and module.exports to export.
Basic CommonJS Export
// math.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = {
add,
subtract
};
Basic CommonJS Import
// main.js
const math = require('./math.js');
console.log(math.add(5, 3)); // 8
console.log(math.subtract(5, 3)); // 2
Export Individual Functions
// utils.js
exports.greet = function(name) {
return `Hello, ${name}!`;
};
exports.farewell = function(name) {
return `Goodbye, ${name}!`;
};
// main.js
const { greet, farewell } = require('./utils.js');
console.log(greet("Alice")); // "Hello, Alice!"
console.log(farewell("Bob")); // "Goodbye, Bob!"
Default Export
// calculator.js
function Calculator() {
this.add = (a, b) => a + b;
this.subtract = (a, b) => a - b;
}
module.exports = Calculator;
// main.js
const Calculator = require('./calculator.js');
const calc = new Calculator();
console.log(calc.add(5, 3)); // 8
Export Single Function
// add.js
module.exports = function(a, b) {
return a + b;
};
// main.js
const add = require('./add.js');
console.log(add(5, 3)); // 8
CommonJS vs ES6 Modules
| Feature | CommonJS | ES6 Modules |
|---|---|---|
| Syntax | require() / module.exports |
import / export |
| Loading | Synchronous | Asynchronous |
| Tree Shaking | No | Yes |
| Static Analysis | Limited | Full |
| Browser Support | Via bundler | Native |
| Node.js | Native | Native (ESM) |
AMD (Asynchronous Module Definition)
AMD is designed for browser environments where modules load asynchronously.
Basic AMD Module
// math.js
define(function() {
return {
add: function(a, b) {
return a + b;
},
subtract: function(a, b) {
return a - b;
}
};
});
AMD with Dependencies
// calculator.js
define(['math'], function(math) {
return {
calculate: function(a, b, operation) {
if (operation === 'add') {
return math.add(a, b);
}
return math.subtract(a, b);
}
};
});
AMD with RequireJS
// Using RequireJS
require(['math', 'calculator'], function(math, calculator) {
console.log(math.add(5, 3));
console.log(calculator.calculate(10, 5, 'add'));
});
Note: AMD is less common now, replaced by ES6 modules and bundlers.
Module Bundlers
Module bundlers combine multiple modules into one or more files for browser use.
Why Bundlers?
- Browser Compatibility: Browsers don't natively support all module systems
- Optimization: Minify, tree-shake, optimize code
- Asset Management: Handle CSS, images, etc.
- Development Tools: Hot reload, source maps
- Code Splitting: Load code on demand
Popular Bundlers
- Webpack: Most popular, highly configurable
- Rollup: Great for libraries, tree-shaking
- Parcel: Zero-configuration bundler
- Vite: Fast development, modern tooling
- esbuild: Extremely fast bundler
Webpack
Webpack is a powerful module bundler that can handle various assets.
Basic Webpack Setup
package.json:
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"build": "webpack",
"dev": "webpack serve"
},
"devDependencies": {
"webpack": "^5.0.0",
"webpack-cli": "^4.0.0"
}
}
webpack.config.js:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
mode: 'development'
};
Webpack Features
- Loaders: Transform files (Babel, TypeScript, CSS)
- Plugins: Extend functionality
- Code Splitting: Split code into chunks
- Hot Module Replacement: Update without refresh
- Source Maps: Debug original code
Rollup
Rollup is optimized for creating libraries and uses ES6 modules.
Basic Rollup Setup
rollup.config.js:
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'es' // ES module format
}
};
Rollup Features
- Tree Shaking: Remove unused code
- ES6 Modules: Native ES6 module support
- Smaller Bundles: Optimized for libraries
- Multiple Formats: ES, CommonJS, UMD
Vite
Vite is a modern build tool that provides fast development experience.
Basic Vite Setup
package.json:
{
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"vite": "^4.0.0"
}
}
Vite Features
- Fast HMR: Instant hot module replacement
- ES Modules: Native ES module support
- Optimized Build: Uses Rollup for production
- Zero Config: Works out of the box
Module System Comparison
When to Use Each
CommonJS:
- Node.js applications
- Legacy codebases
- Server-side JavaScript
ES6 Modules:
- Modern JavaScript projects
- Browser applications
- When you need tree-shaking
- Modern Node.js (with ESM)
AMD:
- Legacy browser applications
- RequireJS projects
- (Generally avoid for new projects)
Bundlers:
- Browser applications
- When you need optimization
- Complex build requirements
- Asset management
Practical Examples
Example 1: CommonJS Module
// user.js
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
getInfo() {
return `${this.name} (${this.email})`;
}
}
module.exports = User;
// main.js
const User = require('./user.js');
let user = new User("Alice", "alice@example.com");
console.log(user.getInfo());
Example 2: CommonJS with Multiple Exports
// math.js
exports.add = (a, b) => a + b;
exports.subtract = (a, b) => a - b;
exports.multiply = (a, b) => a * b;
exports.divide = (a, b) => a / b;
// main.js
const { add, subtract, multiply, divide } = require('./math.js');
console.log(add(5, 3)); // 8
console.log(multiply(4, 2)); // 8
Example 3: Mixed Exports
// utils.js
function formatDate(date) {
return date.toLocaleDateString();
}
function formatCurrency(amount) {
return `$${amount.toFixed(2)}`;
}
// Named exports
exports.formatDate = formatDate;
exports.formatCurrency = formatCurrency;
// Default export
module.exports.default = {
formatDate,
formatCurrency
};
Practice Exercise
Exercise: Module Systems
Objective: Practice using different module systems and understand bundlers.
Instructions:
- Create CommonJS modules
- Convert to ES6 modules
- Understand bundler concepts
- Compare module systems
Example Solution:
// CommonJS Example
// math.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function multiply(a, b) {
return a * b;
}
function divide(a, b) {
if (b === 0) {
throw new Error("Division by zero");
}
return a / b;
}
module.exports = {
add,
subtract,
multiply,
divide
};
// Alternative syntax
// exports.add = add;
// exports.subtract = subtract;
// main.js (CommonJS)
const math = require('./math.js');
console.log("=== CommonJS Module ===");
console.log("Add:", math.add(5, 3)); // 8
console.log("Subtract:", math.subtract(5, 3)); // 2
console.log("Multiply:", math.multiply(4, 2)); // 8
console.log("Divide:", math.divide(10, 2)); // 5
// Destructuring
const { add, subtract } = require('./math.js');
console.log("Destructured:", add(10, 5)); // 15
// ES6 Module Equivalent
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
}
export function divide(a, b) {
if (b === 0) {
throw new Error("Division by zero");
}
return a / b;
}
// main.js (ES6)
import { add, subtract, multiply, divide } from './math.js';
console.log("=== ES6 Module ===");
console.log("Add:", add(5, 3));
console.log("Subtract:", subtract(5, 3));
console.log("Multiply:", multiply(4, 2));
console.log("Divide:", divide(10, 2));
// CommonJS: User Module
// user.js
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
getInfo() {
return `${this.name} (${this.email})`;
}
}
module.exports = User;
// main.js
const User = require('./user.js');
let user = new User("Alice", "alice@example.com");
console.log("User:", user.getInfo());
// CommonJS: Configuration
// config.js
const config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3
};
module.exports = config;
// main.js
const config = require('./config.js');
console.log("Config:", config);
Expected Output:
=== CommonJS Module ===
Add: 8
Subtract: 2
Multiply: 8
Divide: 5
Destructured: 15
=== ES6 Module ===
Add: 8
Subtract: 2
Multiply: 8
Divide: 5
User: Alice (alice@example.com)
Config: { apiUrl: "https://api.example.com", timeout: 5000, retries: 3 }
Challenge (Optional):
- Set up a Webpack project
- Set up a Rollup project
- Convert CommonJS to ES6 modules
- Create a module library
Common Mistakes
1. Mixing Module Systems
// ⚠️ Problem: Mixing CommonJS and ES6
// module1.js (CommonJS)
module.exports = { add };
// module2.js (ES6)
import { add } from './module1.js'; // May not work
// ✅ Solution: Use one system consistently
2. Circular Dependencies
// ⚠️ Problem: Circular dependency
// module1.js
const { func2 } = require('./module2.js');
// module2.js
const { func1 } = require('./module1.js'); // Circular!
// ✅ Solution: Restructure to avoid
3. Wrong Export Syntax
// ⚠️ Problem: Wrong syntax
exports = { add }; // Doesn't work
// ✅ Solution: Use module.exports or exports.property
module.exports = { add };
// or
exports.add = add;
4. Forgetting File Extension
// ⚠️ Problem: May not work in all environments
const math = require('./math');
// ✅ Solution: Include extension (optional in CommonJS, required in ES6)
const math = require('./math.js');
Key Takeaways
- CommonJS: Node.js standard, uses
require()andmodule.exports - AMD: Browser-focused, asynchronous loading (legacy)
- ES6 Modules: Modern standard,
import/export - Bundlers: Combine modules for browsers (Webpack, Rollup, Vite)
- Choose Wisely: Use ES6 for new projects, CommonJS for Node.js
- Bundlers Essential: Needed for browser applications
- Best Practice: Use consistent module system
- Modern Approach: ES6 modules with bundler
Quiz: Module Systems
Test your understanding with these questions:
-
CommonJS uses:
- A) import/export
- B) require/module.exports
- C) define/require
- D) module/import
-
ES6 modules use:
- A) require/module.exports
- B) import/export
- C) define/require
- D) module/require
-
CommonJS is:
- A) Asynchronous
- B) Synchronous
- C) Both
- D) Neither
-
AMD stands for:
- A) Asynchronous Module Definition
- B) Advanced Module Definition
- C) Application Module Definition
- D) Automatic Module Definition
-
Webpack is a:
- A) Module system
- B) Module bundler
- C) Framework
- D) Library
-
Rollup is optimized for:
- A) Applications
- B) Libraries
- C) Both
- D) Neither
-
Modern projects should use:
- A) CommonJS only
- B) ES6 modules
- C) AMD
- D) No modules
Answers:
- B) require/module.exports
- B) import/export
- B) Synchronous
- A) Asynchronous Module Definition
- B) Module bundler
- B) Libraries
- B) ES6 modules
Next Steps
Congratulations! You've completed Module 11: Modules. You now know:
- How ES6 modules work
- How CommonJS works
- About module bundlers
- When to use each system
What's Next?
- Module 12: Working with APIs
- Lesson 12.1: Fetch API
- Practice building modular applications
- Continue learning advanced JavaScript
Additional Resources
- Node.js Modules: nodejs.org/api/modules.html
- Webpack Documentation: webpack.js.org
- Rollup Documentation: rollupjs.org
- Vite Documentation: vitejs.dev
Lesson completed! You've finished Module 11: Modules. Ready for Module 12: Working with APIs!
Course Navigation
- ES6 Modules
- CommonJS and Module Systems
- ES6 Modules
- CommonJS and Module Systems