1. What Are Modules?

  • Modules are individual blocks of reusable code in Node.js.
  • Each file in Node.js is treated as a module, encapsulating code and making it reusable in other parts of the application.
  • Helps in organizing code and promoting reusability.

2. Types of Modules

Node.js modules come in different forms:

  • Core Modules: Built-in modules that come with Node.js, like fs, http, path, events, etc.
  • Local/User-Defined Modules: Custom modules created by the developer in the project.
  • Third-Party Modules: Modules installed from npm (Node Package Manager), like express, mongoose, lodash, etc.

3. Core Modules

  • These are part of the Node.js runtime environment, and you can use them without installing anything.
  • Example:
const fs = require('fs'); // 'fs' is a core module for file system operations.

4. Local/User-Defined Modules

  • Any JavaScript file you create can be a module.
  • You can export functions, objects, or variables from one file and import them into another using module.exports and require. Example:
  1. Exporting from a module (math.js):
// math.js
function add(a, b) {
    return a + b;
}
 
module.exports = { add };
  1. Importing in another file (app.js):
const math = require('./math');
console.log(math.add(5, 10)); // Output: 15

5. Third-Party Modules (npm)

  • These are modules you install using npm (Node Package Manager).
  • Example:
npm install lodash

6. How to Export from a Module

Node.js provides a couple of ways to export code from a module:

  • module.exports: This allows you to export functions, objects, classes, etc. For example:
// math.js
module.exports.add = function (a, b) {
  return a + b;
};
  • exports: A shorthand for module.exports. However, assigning a value directly to exports can break its reference to module.exports.

Example of shorthand:

// math.js
exports.add = function (a, b) {
  return a + b;
};
  • Important Note: If you assign something directly to exports, like exports = {} or exports = someFunction, it will no longer point to module.exports.

7. How to Import a Module

  • require(): Use require() to import a module.
    • It can import core, local, and third-party modules.
    • Example:
const math = require('./math');
const fs = require('fs'); // core module
const _ = require('lodash'); // npm module

8. Module Caching

  • Node.js caches modules after they are loaded for the first time.
  • If you require the same module multiple times, Node.js will return the cached version instead of reloading it.
  • This enhances performance, but you can bypass this by clearing the cache or forcing the module to reload.

9. ES6 Modules (ESM) in Node.js

  • Starting with Node.js 12+, ECMAScript Modules (ESM) are supported with .mjs files or by using the "type": "module" field in the package.json.
  • ESM uses import and export syntax, which is different from CommonJS (require() and module.exports).

10. Resolving Modules

  • Node.js resolves modules in the following order:
    1. Core Modules (e.g., http, fs, etc.)
    2. Relative Path Modules (e.g., ./math)
    3. Node Modules (from node_modules folder)
    4. Absolute Paths (if using custom path configurations)
  • If no module is found, Node.js throws a MODULE_NOT_FOUND error.

11. Node Package Manager (npm)

  • npm is the default package manager for Node.js, which allows developers to install, share, and manage third-party modules.
  • Commands:
    • npm install <package>: Installs a package.
    • npm uninstall <package>: Removes a package.
    • npm update: Updates packages.
    • npm init: Initializes a new Node.js project and generates a package.json.

12. package.json

  • package.json is a manifest file in every Node.js project.
  • It holds metadata about the project and lists dependencies (modules required for the project).

13. Transpiling with Babel (for using ES6 in older Node.js versions)

  • Node.js has partial support for ES6 modules. For full ES6+ feature support, developers use Babel to transpile ES6 code into ES5 (CommonJS) so it can run in Node.js.

14. Common Errors

  • MODULE_NOT_FOUND: Module couldn’t be found, often due to incorrect path or missing module installation.
  • Cannot use import/export outside a module: Happens if you try to use ES6 import/export in a CommonJS context without proper configuration (like "type": "module" in package.json).

15. CJS vs ESM

In Node.js, ESM (ECMAScript Modules) and CommonJS (CJS) are two module systems used to organize and manage code. They differ in syntax, usage, and how they handle imports and exports.

1. CommonJS (CJS) Modules

CommonJS was the original module system in Node.js and is widely used in many Node.js applications. It’s synchronous, designed to work on the server-side in environments like Node.js.

Key Features:

  • Importing Modules: You use require() to import other modules.
  • Exporting Modules: You use module.exports or exports to export modules.
  • Synchronous Loading: Modules are loaded synchronously, which makes it suitable for server-side environments where blocking code isn’t a major concern.
  • File Extension: CommonJS modules usually have the .js extension.

Example of CommonJS Syntax:

// Exporting in CommonJS
module.exports = function greet() {
  return 'Hello, world!';
};
 
// Importing in CommonJS
const greet = require('./greet');
console.log(greet()); // Outputs: Hello, world!

Use Cases:

  • Most widely used in Node.js.
  • Supported in all versions of Node.js.
  • Many existing Node.js modules and packages use CommonJS.

2. ESM (ECMAScript Modules)

ECMAScript Modules (ESM) is the standardized module system introduced in JavaScript (ES6, or ES2015). It’s the official module system for JavaScript, and Node.js has gradually adopted it to stay aligned with the evolving JavaScript standard.

Key Features:

  • Importing Modules: You use the import keyword to import other modules.
  • Exporting Modules: You use the export keyword to export modules.
  • Asynchronous Loading: ESM modules are loaded asynchronously, making them better suited for environments like the browser, where non-blocking operations are important.
  • File Extension: ESM modules can have .mjs extension or can use .js with a "type": "module" field in package.json.

Example of ESM Syntax:

// Exporting in ESM
export function greet() {
  return 'Hello, world!';
}
 
// Importing in ESM
import { greet } from './greet.mjs';
console.log(greet()); // Outputs: Hello, world!

Use Cases:

  • The preferred module system for new JavaScript/Node.js code.
  • Asynchronous module loading makes it more suitable for modern web applications.
  • Aligns with the JavaScript standard (used in browsers).

Differences Between ESM and CommonJS

FeatureESMCommonJS (CJS)
Import syntaximportrequire
Export syntaxexport, export defaultmodule.exports, exports
LoadingAsynchronousSynchronous
File extension.mjs or .js (with "type": "module").js
Default exportsSupports export defaultNo native default export
Support in Node.jsNode 12+ (Stable in Node 14+)Supported in all versions

How to Use ESM in Node.js

By default, Node.js treats files with a .js extension as CommonJS modules. However, to use ESM syntax (import/export), you can:

  1. Use the .mjs Extension: Node.js will treat .mjs files as ESM modules.
  2. Set "type": "module" in package.json: You can also set "type": "module" in your package.json to tell Node.js that all .js files should be treated as ESM modules.

Example:

// package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "type": "module"
}

Interoperability

Node.js provides limited interoperability between ESM and CommonJS modules:

  • CJS to ESM: You can import CommonJS modules into ESM using import.
  • ESM to CJS: You need to use import() (dynamic import) to load ESM modules into CommonJS.