Learning Node.js - Node.js Core Modules (fs, path, os, events)
Episode 3 of 23

Learning Node.js - Node.js Core Modules (fs, path, os, events)

This episode dissects the four most commonly used core modules: fs for the file system, path for path manipulation, os for system information, and events for EventEmitter. All examples run directly without installing any package.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

One of Node.js's strengths is its core modules — built-in libraries ready to use without installing anything. Of the dozens of modules available, four form the foundation of almost every backend application: fs, path, os, and events.

Episode 3 dissects all four modules. You'll see how to read and write files with fs, compose cross-platform paths with path, read system information with os, and build communication between objects with events. After this episode, you won't be confused anymore when you see require("fs") in production code.

Getting to Know Core Modules

Loading Built-in Modules

Core modules are loaded exactly like npm packages, except there's no install step. Two syntaxes apply: CommonJS and ES Modules. We'll dissect the ES Modules syntax fully in episode 4; for this episode we use CommonJS:

JSLoad core modules
const fs = require("fs");
const path = require("path");
const os = require("os");
const { EventEmitter } = require("events");
 
console.log("Empat modul core berhasil dimuat");

The pattern const { EventEmitter } = require("events") is destructuring — taking just one named property from a module. This is a common pattern for modules that export many things.

The fs Module: File System

Reading and Writing Files

The fs (file system) module is the gateway to the file system: creating folders, reading files, writing files, and even streaming data. Here's the simplest example:

JSRead and write files
const fs = require("fs");
 
fs.writeFileSync("catatan.txt", "Belajar Node.js");
const isi = fs.readFileSync("catatan.txt", "utf8");
console.log(isi);

fs.writeFileSync("catatan.txt", "Belajar Node.js") creates a file and then readFileSync reads it back with the utf8 encoding. The Sync suffix means a blocking version — safe for scripts, but in episode 5 we'll switch to the asynchronous versions that suit servers better.

Exploring Directories

To see the contents of a folder and check whether a file exists:

JSExplore directories
const fs = require("fs");
 
const daftar = fs.readdirSync(".");
console.log(daftar);
console.log(fs.existsSync("catatan.txt"));

fs.readdirSync(".") returns the list of files in the current folder, and existsSync checks whether a path exists. Both functions are often used for validation before file operations.

The path Module: Path Manipulation

Joining Paths Safely

Operating systems use different path separators — Linux and macOS use /, Windows uses \. The path module removes this difference so your code is portable:

JSJoin paths
const path = require("path");
 
console.log(path.join("src", "routes", "api.js"));
console.log(path.extname("server.js"));
console.log(path.basename("/app/src/server.js"));

path.join("src", "routes", "api.js") produces src/routes/api.js on Linux and src\routes\api.js on Windows. Meanwhile extname takes the file extension and basename takes the file name from a full path.

Resolving Absolute Paths

When code runs, the working folder can differ from the file's location. Use __dirname and path.resolve to always point at the correct location:

JSAbsolute paths
const path = require("path");
 
console.log(__dirname);
console.log(path.resolve("src", "config.js"));

__dirname holds the folder location where this file lives. Combining it with path.join is the standard pattern for reading asset files, such as configuration or templates, without depending on the terminal's working folder.

The os Module: System Information

Platform and Resources

The os module gives access to operating system and hardware information. Useful for startup logs, monitoring, and deployment scripts:

JSSystem information
const os = require("os");
 
console.log(os.platform());
console.log(os.cpus().length);
console.log(os.totalmem() / 1024 / 1024 / 1024);

os.platform() returns the system name, os.cpus().length counts the number of CPU cores — this number determines the worker count for clustering in episode 19 — and totalmem reports total RAM in bytes, which we convert to gigabytes.

The events Module: EventEmitter

Communication Between Objects

The events module provides EventEmitter — a pub/sub pattern that underpins many Node.js APIs, including the HTTP server and streams. You can emit and listen for named events:

JSSimple EventEmitter
const { EventEmitter } = require("events");
 
const emitter = new EventEmitter();
emitter.on("sapa", (nama) => {
  console.log("Halo, " + nama);
});
emitter.emit("sapa", "Arman");

emitter.on("sapa", (nama) => ...) registers a listener, then emitter.emit("sapa", "Arman") triggers that event along with its arguments. Imagine using this pattern to tell other components that a file has finished downloading or a database connection has closed.

Four Modules in One Story

In a real application, all four modules often work together: os reports resources, path composes the log file location, fs writes the log, and events notifies other modules that a new log is available. Mastering all four means mastering 80 percent of the basic needs of a Node.js backend.

Closing

Here's what to take away:

  • fs manages files and directories; the Sync versions suit scripts.
  • path unifies cross-platform paths safely.
  • __dirname and path.resolve produce reliable absolute paths.
  • os provides platform, CPU, and memory data.
  • events provides EventEmitter for communication between objects.
  • These four core modules require no package installs at all.

In the next episode, episode 4, we'll discuss CommonJS vs ES Modules — the difference between require and import, the "type": "module" field in package.json, how to mix both systems, and best practices for choosing a module format for new projects. The file I/O and streams foundation will be waiting in episode 5.