جاوا اسکریپت در سمت سرور (Node.js)

JavaScript خارج از مرورگر، Node.js Runtime، ماژول‌های File System و Path و HTTP، Events و Streams و Buffers، Process و Environment Variables و ساخت REST API.

JavaScript خارج از مرورگر

Node.js جاوا اسکریپت را از مرورگر به سرور، ابزار خط فرمان و دسکتاپ برد:

// محیط‌های اجرای JS:
// - مرورگر (Chrome, Firefox) → DOM، window
// - Node.js → fs، http، process
// - Deno / Bun → مدرن‌تر

// تفاوت‌های کلیدی Node:
// ✗ window, document, alert
// ✓ require/import, process, __dirname
// ✓ فایل‌سیستم، شبکه، دیتابیس

Node.js Runtime

موتور V8 + APIهای سیستمی:

// بررسی نسخه:
// node --version

// اجرای فایل:
// node app.js

// REPL تعاملی:
// node
// > 2 + 2
// 4

// globals مخصوص Node:
console.log(__dirname);   // پوشه فایل فعلی
console.log(__filename);  // مسیر کامل فایل
console.log(process.version);
console.log(process.platform);  // win32 / linux

File System — فایل‌سیستم

const fs = require("node:fs");

// خواندن همگام — блок‌کننده:
const data = fs.readFileSync("file.txt", "utf8");
console.log(data);

// خواندن ناهمگام — Callback:
fs.readFile("file.txt", "utf8", (err, data) => {
    if (err) throw err;
    console.log(data);
});

// ناهمگام — Promise (توصیه‌شده):
const fsPromises = require("node:fs/promises");

async function readFile() {
    try {
        const data = await fsPromises.readFile("file.txt", "utf8");
        console.log(data);
    } catch (err) {
        console.error("خطا:", err.message);
    }
}

// نوشتن:
await fsPromises.writeFile("output.txt", "سلام دنیا");
await fsPromises.appendFile("log.txt", "لاگ جدید\n");

// سایر عملیات:
const stats = await fsPromises.stat("file.txt");
console.log(stats.size, stats.isFile());

await fsPromises.mkdir("new-folder", { recursive: true });
await fsPromises.copyFile("a.txt", "b.txt");
await fsPromises.rename("old.txt", "new.txt");
await fsPromises.unlink("delete.txt");   // حذف
await fsPromises.rm("folder", { recursive: true });  // حذف پوشه

Path — مسیرها

const path = require("node:path");

// join — ساخت امن (چند-پلتفرمی):
const filePath = path.join("folder", "sub", "file.txt");
console.log(filePath);  // folder\sub\file.txt (ویندوز)

// resolve — مسیر مطلق:
console.log(path.resolve("data", "db.json"));
// C:\project\data\db.json

// اجزا:
console.log(path.parse("/users/ali/file.txt"));
// { dir: "/users/ali", base: "file.txt",
//   ext: ".txt", name: "file" }

console.log(path.extname("photo.jpg"));   // .jpg
console.log(path.basename("/a/b/c.txt")); // c.txt
console.log(path.dirname("/a/b/c.txt"));  // /a/b

// __dirname + path:
const configPath = path.join(__dirname, "config.json");

HTTP Server — سرور وب

const http = require("node:http");

// سرور ساده:
const server = http.createServer((req, res) => {
    // req — درخواست:
    console.log(req.method);   // GET / POST
    console.log(req.url);      // /api/users

    // res — پاسخ:
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ message: "سلام" }));
});

server.listen(3000, () => {
    console.log("سرور روی پورت 3000");
});

// مسیریابی دستی:
const server2 = http.createServer((req, res) => {
    if (req.method === "GET" && req.url === "/") {
        res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
        res.end("<h1>صفحه اصلی</h1>");
    } else if (req.method === "GET" && req.url === "/api/users") {
        const users = [{ id: 1, name: "علی" }];
        res.writeHead(200, { "Content-Type": "application/json" });
        res.end(JSON.stringify(users));
    } else {
        res.writeHead(404);
        res.end("یافت نشد");
    }
});

Events — رویدادها در Node

const EventEmitter = require("node:events");

// ساخت ایمتر:
const emitter = new EventEmitter();

// شنیدن:
emitter.on("greet", (name) => {
    console.log(`سلام ${name}!`);
});

// فقط یک‌بار:
emitter.once("init", () => console.log("شروع"));

// پرتاب:
emitter.emit("greet", "علی");   // سلام علی!
emitter.emit("greet", "سارا");  // سلام سارا!
emitter.emit("init");           // شروع
emitter.emit("init");           // سکوت — once!

// حذف:
const handler = () => console.log("هندلر");
emitter.on("x", handler);
emitter.off("x", handler);

// کلاس سفارشی:
class Database extends EventEmitter {
            connect() {
                this.emit("connected");
            }
        }

Streams — جریان داده

پردازش داده قطعه‌به‌قطعه بدون بارگذاری کامل:

const fs = require("node:fs");

// مشکل — کل فایل ۲GB در حافظه: ❌
const data = fs.readFileSync("video.mp4");

// راه‌حل — Stream: ✓
const readStream = fs.createReadStream("big-file.txt", "utf8");

readStream.on("data", (chunk) => {
    console.log("قطعه جدید:", chunk.length, "کاراکتر");
});

readStream.on("end", () => console.log("تمام شد"));
readStream.on("error", (err) => console.error(err));

// کپی با pipe — ساده:
const reader = fs.createReadStream("source.txt");
const writer = fs.createWriteStream("dest.txt");
reader.pipe(writer);  // خودکار جریان!

Buffers — بافرهای Node

// Buffer — داده باینری در Node:
const buf = Buffer.from("سلام", "utf8");
console.log(buf);            // <Buffer d8 b3 ...>
console.log(buf.length);     // 8 بایت
console.log(buf.toString("utf8")); // سلام

// ساخت با طول مشخص:
const buf2 = Buffer.alloc(16);      // صفرها
const buf3 = Buffer.allocUnsafe(16); // بدون پاک‌سازی — سریع

// نوشتن و خواندن:
buf2.write("Hello");
console.log(buf2.toString());

// تبدیل:
const str = Buffer.from("base64-data", "base64").toString("utf8");
const b64 = Buffer.from("متن").toString("base64");

Process — فرآیند

// اطلاعات:
console.log(process.pid);        // شناسه فرآیند
console.log(process.cwd());      // پوشه فعلی
console.log(process.platform);   // win32

// آرگومان‌های خط فرمان:
// node app.js --port 3000
console.log(process.argv);
// [node, app.js, --port, 3000]

// پارس آرگومان:
const args = process.argv.slice(2);
const portIdx = args.indexOf("--port");
const port = portIdx > -1 ? args[portIdx + 1] : 3000;

// env — متغیرهای محیطی:
console.log(process.env.HOME);
console.log(process.env.NODE_ENV);  // development/production

// خروج:
process.exit(0);   // موفق
process.exit(1);   // خطا

// رویداد خروج:
process.on("exit", (code) => {
    console.log("خروج با کد:", code);
});

// خطای گرفته‌نشده:
process.on("uncaughtException", (err) => {
    console.error("خطای مهلک:", err);
    process.exit(1);
});

Environment Variables

// تنظیم — خط فرمان:
// set PORT=3000        (ویندوز)
// PORT=3000 node app   (لینوکس)

// خواندن:
const PORT = process.env.PORT || 3000;

// فایل .env + dotenv:
// npm install dotenv
require("dotenv").config();

// حالا از .env خوانده می‌شود:
const dbUrl = process.env.DATABASE_URL;

// .env:
// PORT=3000
// DATABASE_URL=mongodb://localhost:27017/app
// JWT_SECRET=mysecret

// ⚠️ .env در .gitignore!

Timers در Node

// همان مرورگر + نسخه Node:
setTimeout(() => console.log("بعد از ۱ ثانیه"), 1000);

setInterval(() => console.log("هر ثانیه"), 1000);

// مخصوص Node:
setImmediate(() => {
    console.log("بعد از عملیات I/O فعلی");
});

process.nextTick(() => {
    console.log("قبل از هر چیز دیگر");
});

// ترتیب:
process.nextTick(() => console.log("1 — nextTick"));
setImmediate(() => console.log("2 — immediate"));
setTimeout(() => console.log("3 — timeout"), 0);
// معمولاً: 1 → 3 → 2

ساخت REST API کامل

const http = require("node:http");
const fs = require("node:fs/promises");
const path = require("node:path");

// دیتابیس ساده — فایل JSON:
const DB_FILE = path.join(__dirname, "db.json");

async function readDB() {
    try {
        const data = await fs.readFile(DB_FILE, "utf8");
        return JSON.parse(data);
    } catch {
        return { users: [] };
    }
}

async function writeDB(db) {
    await fs.writeFile(DB_FILE, JSON.stringify(db, null, 2));
}

// سرور:
const server = http.createServer(async (req, res) => {
    const url = new URL(req.url, `http://${req.headers.host}`);
    const json = (code, data) => {
        res.writeHead(code, { "Content-Type": "application/json" });
        res.end(JSON.stringify(data));
    };

    try {
        // GET /api/users:
        if (req.method === "GET" && url.pathname === "/api/users") {
            const db = await readDB();
            return json(200, db.users);
        }

        // POST /api/users:
        if (req.method === "POST" && url.pathname === "/api/users") {
            let body = "";
            for await (const chunk of req) body += chunk;

            const userData = JSON.parse(body);
            if (!userData.name) {
                return json(422, { error: "نام الزامی است" });
            }

            const db = await readDB();
            const user = {
                id: Date.now(),
                name: userData.name,
                email: userData.email || null
            };
            db.users.push(user);
            await writeDB(db);
            return json(201, user);
        }

        // GET /api/users/:id:
        const match = url.pathname.match(/^\/api\/users\/(\d+)$/);
        if (req.method === "GET" && match) {
            const db = await readDB();
            const user = db.users.find(u => u.id === Number(match[1]));
            return user ? json(200, user) : json(404, { error: "یافت نشد" });
        }

        json(404, { error: "مسیر یافت نشد" });
    } catch (e) {
        json(500, { error: e.message });
    }
});

server.listen(process.env.PORT || 3000);

مدیریت Packageها در Node

// ساخت پروژه:
// npm init -y

// node_modules — کد نصب‌شده:
// ├── lodash/
// ├── express/
// └── ...

// package.json — تنظیمات:
// dependencies     — تولیدی
// devDependencies — توسعه

// اجرای محلی پکیج‌ها:
// npx eslint .

// اسکریپت main:
{
    "main": "server.js",
    "scripts": {
        "start": "node server.js",
        "dev": "nodemon server.js"
    }
}

برنامه خط فرمان (CLI)

#!/usr/bin/env node
// فایل cli.js

const args = process.argv.slice(2);
const command = args[0];

switch (command) {
    case "init":
        console.log("راه‌اندازی پروژه...");
        break;

    case "build":
        console.log("ساخت...");
        break;

    default:
        console.log(`
        استفاده: cli.js <command>

        دستورات:
          init    راه‌اندازی
          build   ساخت
        `);
}

// package.json:
{
    "bin": {
        "mycli": "./cli.js"
    }
}
// npm link → mycli build

جمع‌بندی

ماژولکاربرد
fsفایل و پوشه
pathمسیرهای امن
httpسرور و کلاینت
eventsEventEmitter
streamداده جاری
processمحیط و کنترل

این مبحث بخشی از دوره آموزش کامل جاوا اسکریپت است.

ابزارهای مرتبط