Node.js
الوحدات ونظام الملفات في Node.js — دليل شامل 2026
📅 2026-11-03⏱ 8 دقائق قراءة
في المقال السابق، كتبت أول برنامج Node.js. الآن سنتعمق في **الوحدات (Modules)** و **نظام الملفات (File System)** — وهما أساس أي تطبيق Node.js حقيقي.
في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم الوحدات ونظام الملفات، مع تمارين وحلول.
## ما هي الوحدة (Module)؟
**الوحدة** هي **ملف JavaScript** يمكن استيراده في ملفات أخرى.
**الفكرة:** بدلاً من كتابة كل الكود في ملف واحد كبير، نقسمه إلى وحدات صغيرة:
- **`math.js`** — دوال رياضية.
- **`user.js`** — دوال المستخدم.
- **`database.js`** — دوال قاعدة البيانات.
**الفائدة:**
- تنظيم الكود.
- إعادة الاستخدام.
- سهولة الصيانة.
## نظاما الوحدات في Node.js
<table>
<thead>
<tr>
<th>المعيار</th>
<th>CommonJS</th>
<th>ES Modules</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>الصيغة</strong></td>
<td><code>require</code> / <code>module.exports</code></td>
<td><code>import</code> / <code>export</code></td>
</tr>
<tr>
<td><strong>الامتداد</strong></td>
<td><code>.js</code></td>
<td><code>.mjs</code> أو <code>"type": "module"</code></td>
</tr>
<tr>
<td><strong>الحداثة</strong></td>
<td>قديم (افتراضي)</td>
<td>حديث (ES6)</td>
</tr>
<tr>
<td><strong>الاستخدام</strong></td>
<td>شائع في Node.js</td>
<td>المعيار الحديث</td>
</tr>
</tbody>
</table>
## CommonJS — الطريقة التقليدية
### 1. تصدير دالة واحدة
**`greet.js`:**
```javascript
function greet(name) {
return `مرحباً ${name}!`;
}
module.exports = greet;
```
**`index.js`:**
```javascript
const greet = require("./greet");
console.log(greet("أحمد")); // مرحباً أحمد!
```
### 2. تصدير عدة دوال (كائن)
**`math.js`:**
```javascript
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = { add, subtract };
```
**`index.js`:**
```javascript
const math = require("./math");
console.log(math.add(5, 3)); // 8
console.log(math.subtract(5, 3)); // 2
```
**أو باستخدام Destructuring:**
```javascript
const { add, subtract } = require("./math");
console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
```
### 3. تصدير مباشر
**`user.js`:**
```javascript
exports.name = "أحمد";
exports.age = 25;
exports.email = "ahmed@example.com";
```
**أو:**
```javascript
module.exports = {
name: "أحمد",
age: 25,
email: "ahmed@example.com",
};
```
## ES Modules — الطريقة الحديثة
### 1. الإعداد
**في `package.json`:**
```json
{
"type": "module"
}
```
**أو** استخدم امتداد `.mjs`:
```
math.mjs
index.mjs
```
### 2. تصدير مُسمّى (Named Export)
**`math.js`:**
```javascript
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
```
**`index.js`:**
```javascript
import { add, subtract } from "./math.js";
console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
```
### 3. تصدير افتراضي (Default Export)
**`greet.js`:**
```javascript
export default function greet(name) {
return `مرحباً ${name}!`;
}
```
**`index.js`:**
```javascript
import greet from "./greet.js";
console.log(greet("أحمد")); // مرحباً أحمد!
```
### 4. خلط التصديرين
**`utils.js`:**
```javascript
export default function main() {
return "الدالة الرئيسية";
}
export function helper() {
return "دالة مساعدة";
}
```
**`index.js`:**
```javascript
import main, { helper } from "./utils.js";
```
## جدول مقارنة سريعة
<table>
<thead>
<tr>
<th>العملية</th>
<th>CommonJS</th>
<th>ES Modules</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>التصدير</strong></td>
<td><code>module.exports = ...</code></td>
<td><code>export ...</code></td>
</tr>
<tr>
<td><strong>الاستيراد</strong></td>
<td><code>require("...")</code></td>
<td><code>import ... from "..."</code></td>
</tr>
<tr>
<td><strong>الامتداد</strong></td>
<td><code>.js</code></td>
<td><code>.mjs</code> أو <code>"type": "module"</code></td>
</tr>
</tbody>
</table>
## نظام الملفات (fs)
**`fs`** هي وحدة مدمجة للتعامل مع الملفات والمجلدات.
### 1. استيراد `fs`
**CommonJS:**
```javascript
const fs = require("fs");
```
**ES Modules:**
```javascript
import fs from "fs";
```
**مع Promise (موصى به):**
```javascript
const fs = require("fs/promises");
// أو
import fs from "fs/promises";
```
### 2. قراءة ملف (متزامن)
```javascript
const fs = require("fs");
const content = fs.readFileSync("file.txt", "utf-8");
console.log(content);
```
**⚠️ تحذير:** `readFileSync` **يحجب** التنفيذ حتى ينتهي.
### 3. قراءة ملف (غير متزامن — موصى به)
**مع Callback:**
```javascript
const fs = require("fs");
fs.readFile("file.txt", "utf-8", (err, data) => {
if (err) {
console.error("خطأ:", err.message);
return;
}
console.log(data);
});
```
**مع Promise:**
```javascript
const fs = require("fs/promises");
async function readFile() {
try {
const content = await fs.readFile("file.txt", "utf-8");
console.log(content);
} catch (error) {
console.error("خطأ:", error.message);
}
}
readFile();
```
### 4. كتابة ملف
```javascript
const fs = require("fs/promises");
async function writeFile() {
try {
await fs.writeFile("output.txt", "مرحباً من Node.js!");
console.log("تم الكتابة!");
} catch (error) {
console.error("خطأ:", error.message);
}
}
writeFile();
```
### 5. إضافة إلى ملف (Append)
```javascript
const fs = require("fs/promises");
await fs.appendFile("log.txt", "سطر جديد\n");
```
### 6. حذف ملف
```javascript
const fs = require("fs/promises");
await fs.unlink("old-file.txt");
```
### 7. التحقق من وجود ملف
```javascript
const fs = require("fs/promises");
async function fileExists(path) {
try {
await fs.access(path);
return true;
} catch {
return false;
}
}
console.log(await fileExists("file.txt"));
```
## العمل مع المجلدات
### 1. إنشاء مجلد
```javascript
const fs = require("fs/promises");
// إنشاء مجلد
await fs.mkdir("new-folder");
// إنشاء مجلدات متداخلة
await fs.mkdir("a/b/c", { recursive: true });
```
### 2. قراءة محتوى مجلد
```javascript
const fs = require("fs/promises");
const files = await fs.readdir("./");
console.log(files); // ["file1.js", "file2.txt", ...]
```
### 3. حذف مجلد
```javascript
const fs = require("fs/promises");
// حذف مجلد فارغ
await fs.rmdir("empty-folder");
// حذف مجلد ومحتواه
await fs.rm("folder", { recursive: true, force: true });
```
## مثال عملي: دفتر ملاحظات
**`notes.js`:**
```javascript
const fs = require("fs/promises");
const path = require("path");
const NOTES_FILE = "notes.json";
// قراءة الملاحظات
async function getNotes() {
try {
const data = await fs.readFile(NOTES_FILE, "utf-8");
return JSON.parse(data);
} catch {
return [];
}
}
// إضافة ملاحظة
async function addNote(text) {
const notes = await getNotes();
const newNote = {
id: Date.now(),
text,
createdAt: new Date().toISOString(),
};
notes.push(newNote);
await fs.writeFile(NOTES_FILE, JSON.stringify(notes, null, 2));
return newNote;
}
// حذف ملاحظة
async function deleteNote(id) {
const notes = await getNotes();
const filtered = notes.filter((n) => n.id !== id);
await fs.writeFile(NOTES_FILE, JSON.stringify(filtered, null, 2));
}
// عرض الملاحظات
async function listNotes() {
const notes = await getNotes();
if (notes.length === 0) {
console.log("لا توجد ملاحظات");
return;
}
notes.forEach((note) => {
console.log(`[${note.id}] ${note.text}`);
});
}
module.exports = { getNotes, addNote, deleteNote, listNotes };
```
**`index.js`:**
```javascript
const notes = require("./notes");
async function main() {
await notes.addNote("تعلم Node.js");
await notes.addNote("بناء مشروع");
await notes.listNotes();
}
main();
```
## تمارين عملية
### تمرين 1: وحدة رياضية
أنشئ وحدة `math.js` تحتوي على 4 دوال رياضية.
**الحل:**
```javascript
// 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("لا يمكن القسمة على صفر");
return a / b;
}
module.exports = { add, subtract, multiply, divide };
```
### تمرين 2: قراءة ملف
اقرأ ملف نصي واطبع محتواه.
**الحل:**
```javascript
const fs = require("fs/promises");
async function readAndPrint(file) {
try {
const content = await fs.readFile(file, "utf-8");
console.log(content);
} catch (error) {
console.error("خطأ:", error.message);
}
}
readAndPrint("file.txt");
```
### تمرين 3: كتابة ملف
اكتب ملفاً يحتوي على قائمة أسماء.
**الحل:**
```javascript
const fs = require("fs/promises");
async function writeNames() {
const names = ["أحمد", "محمد", "علي"];
await fs.writeFile("names.txt", names.join("\n"));
console.log("تم!");
}
writeNames();
```
### تمرين 4: سجل الأخطاء
أنشئ وحدة تسجل الأخطاء في ملف.
**الحل:**
```javascript
const fs = require("fs/promises");
async function logError(message) {
const timestamp = new Date().toISOString();
const line = `[${timestamp}] ${message}\n`;
await fs.appendFile("errors.log", line);
}
module.exports = { logError };
```
### تمرين 5: عد الأسطر
اقرأ ملفاً واحسب عدد أسطره.
**الحل:**
```javascript
const fs = require("fs/promises");
async function countLines(file) {
const content = await fs.readFile(file, "utf-8");
return content.split("\n").length;
}
countLines("file.txt").then(console.log);
```
### تمرين 6: نسخ ملف
انسخ ملفاً إلى مكان آخر.
**الحل:**
```javascript
const fs = require("fs/promises");
async function copyFile(src, dest) {
const content = await fs.readFile(src);
await fs.writeFile(dest, content);
console.log("تم النسخ!");
}
copyFile("source.txt", "backup.txt");
```
### تمرين 7: عرض محتوى مجلد
اعرض كل ملفات مجلد معين.
**الحل:**
```javascript
const fs = require("fs/promises");
async function listFiles(dir) {
const files = await fs.readdir(dir);
files.forEach((file) => console.log(file));
}
listFiles("./");
```
### تمرين 8: دفتر ملاحظات كامل
أنشئ تطبيق دفتر ملاحظات كامل (إضافة، حذف، عرض).
**الحل:** (راجع المثال العملي أعلاه)
## حل المشاكل الشائعة
### 🔴 المشكلة 1: `ENOENT: no such file or directory`
**السبب:** الملف غير موجود.
**الحل:** تحقق من المسار، أو أنشئ الملف:
```javascript
try {
await fs.readFile("file.txt", "utf-8");
} catch (error) {
if (error.code === "ENOENT") {
console.log("الملف غير موجود");
}
}
```
### 🔴 المشكلة 2: `Cannot find module 'xxx'`
**السبب:** الوحدة غير موجودة.
**الحل:** تحقق من:
- المسار (`./` للوحدة المحلية).
- الاسم.
- الامتداد.
### 🔴 المشكلة 3: `require is not defined`
**السبب:** استخدمت `"type": "module"` في `package.json`، لكنك تستخدم `require`.
**الحل:**
```javascript
// بدلاً من require:
import fs from "fs";
```
### 🔴 المشكلة 4: `import` لا يعمل
**السبب:** لم تُضف `"type": "module"`.
**الحل:**
```json
{
"type": "module"
}
```
### 🔴 المشكلة 5: `Cannot use import statement outside a module`
**السبب:** نفس المشكلة السابقة.
**الحل:** أضف `"type": "module"` في `package.json`.
## جدول دوال `fs`
<table>
<thead>
<tr>
<th>الدالة</th>
<th>الوظيفة</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>fs.readFile()</code></td>
<td>قراءة ملف</td>
</tr>
<tr>
<td><code>fs.writeFile()</code></td>
<td>كتابة ملف</td>
</tr>
<tr>
<td><code>fs.appendFile()</code></td>
<td>إضافة لملف</td>
</tr>
<tr>
<td><code>fs.unlink()</code></td>
<td>حذف ملف</td>
</tr>
<tr>
<td><code>fs.mkdir()</code></td>
<td>إنشاء مجلد</td>
</tr>
<tr>
<td><code>fs.readdir()</code></td>
<td>قراءة محتوى مجلد</td>
</tr>
<tr>
<td><code>fs.rm()</code></td>
<td>حذف مجلد</td>
</tr>
<tr>
<td><code>fs.access()</code></td>
<td>التحقق من الوجود</td>
</tr>
</tbody>
</table>
## قائمة تحقق نهائية
<table>
<thead>
<tr>
<th>المهمة</th>
<th>الحالة</th>
</tr>
</thead>
<tbody>
<tr>
<td>فهم الوحدات (Modules)</td>
<td>⬜</td>
</tr>
<tr>
<td>استخدام <code>require</code> و <code>module.exports</code></td>
<td>⬜</td>
</tr>
<tr>
<td>استخدام <code>import</code> و <code>export</code></td>
<td>⬜</td>
</tr>
<tr>
<td>قراءة وكتابة الملفات</td>
<td>⬜</td>
</tr>
<tr>
<td>العمل مع المجلدات</td>
<td>⬜</td>
</tr>
<tr>
<td>بناء دفتر ملاحظات</td>
<td>⬜</td>
</tr>
<tr>
<td>حل التمارين الثمانية</td>
<td>⬜</td>
</tr>
</tbody>
</table>
## ماذا بعد هذا المقال؟
الآن بعد أن أتقنت الوحدات ونظام الملفات، أنت جاهز للمقال التالي:
1. **npm وإدارة الحزم** — تثبيت المكتبات.
2. **بناء HTTP Server** — أول سيرفر.
3. **Express.js** — إطار العمل.
## الخلاصة
في هذا المقال، تعلمت:
- ✅ ما هي الوحدات (Modules).
- ✅ CommonJS (`require` / `module.exports`).
- ✅ ES Modules (`import` / `export`).
- ✅ نظام الملفات (`fs`).
- ✅ قراءة وكتابة وحذف الملفات.
- ✅ العمل مع المجلدات.
- ✅ بناء دفتر ملاحظات كامل.
- ✅ حل 8 تمارين عملية.
**تذكر:** الوحدات ونظام الملفات هما أساس أي تطبيق Node.js حقيقي.