fs — File System
Reading, writing, and manipulating files and directories in Node.js — fs/promises, streams, watching files, and common patterns.
A relative path like "config.json" is resolved against the folder you ran node from (process.cwd()), not the folder the script lives in. The same script works when you cd src && node app.js and fails with ENOENT when you run node src/app.js from the project root, which is exactly how npm scripts, cron jobs and Docker containers run it.
// src/app.js -- config.json sits right next to this file
import { readFile } from "fs/promises";
const conf = JSON.parse(await readFile("config.json", "utf-8")); // relative to... where?
console.log("port:", conf.port);
// $ cd src && node app.js -> port: 8080
// $ node src/app.js (from the project root)
// Error: ENOENT: no such file or directory, open 'config.json'Reading and writing files in Node.js
fs module doesn't exist in browsers —
use browser storage APIs (localStorage, IndexedDB, File System Access API) there.
Import the module
// ESM (recommended — .mjs files or "type": "module" in package.json):
import { readFile, writeFile, mkdir, readdir, stat, unlink, rename } from "fs/promises";
import { existsSync } from "fs"; // sync version (ok for startup checks)
// CommonJS (.js files without "type": "module"):
const { readFile, writeFile } = require("fs/promises");Reading files
// Read as string:
const text = await readFile("notes.txt", "utf-8");
console.log(text);
// Read JSON:
const raw = await readFile("config.json", "utf-8");
const conf = JSON.parse(raw);
console.log(conf.port); // 3000
// Read as Buffer (binary — images, PDFs etc.):
const bytes = await readFile("photo.jpg"); // no encoding = Buffer
console.log(bytes.byteLength, "bytes");
// Handle missing files:
try {
const data = await readFile("missing.txt", "utf-8");
} catch (e) {
if (e.code === "ENOENT") console.log("File not found");
else throw e; // something unexpected — re-throw
}The examples above assume the files are in the current working directory. For files that belong to your code, build the path from the script's own location. new URL("config.json", import.meta.url) does it in one step, and fs functions accept the URL directly. (In CommonJS, use path.join(__dirname, "config.json").)
// src/app.js
import { readFile } from "fs/promises";
const configUrl = new URL("config.json", import.meta.url); // relative to THIS file
const conf = JSON.parse(await readFile(configUrl, "utf-8"));
console.log("port:", conf.port);
// $ cd src && node app.js -> port: 8080
// $ node src/app.js -> port: 8080Writing files
// Write string (creates file if it doesn't exist, overwrites if it does):
await writeFile("output.txt", "Hello, World!", "utf-8");
// Write JSON:
const data = { name: "Alice", score: 95 };
await writeFile("user.json", JSON.stringify(data, null, 2));
// Append (add to end of file):
import { appendFile } from "fs/promises";
await appendFile("log.txt", `[${new Date().toISOString()}] Server started
`);Directories
// Create directory (including parents):
await mkdir("dist/css/fonts", { recursive: true }); // won't throw if exists
// List directory:
const files = await readdir("./src");
console.log(files); // ["app.js", "utils.js", "style.css"]
// Filter to only JS files:
const jsFiles = files.filter(f => f.endsWith(".js"));
// Delete a file:
await unlink("old-file.txt");
// Rename / move:
await rename("old-name.txt", "new-name.txt");
await rename("file.txt", "archive/file.txt"); // also moves across dirsOfficial Sources
- Node.js Docs — File system (fs)
- Node.js Docs — File system promises API
- Node.js Docs — stream.pipeline()
The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.