Kodax

الـ Modules في Node.js — Node.js و Express

الوحدات (Modules) في Node.js

كل ملف في Node وحدة لها نطاقها الخاص: المتغيرات لا تتسرب لغيرها إلا ما تصدّره صراحة. يوجد نظامان — ستقابل الاثنين.

1. CommonJS (الأقدم، ما زال شائعاً)

// math.js
const add = (a, b) => a + b;
const PI = 3.14159;
module.exports = { add, PI };
// app.js
const { add, PI } = require("./math");   // ./ = ملف محلي
console.log(add(2, 3), PI);

- require متزامن، ويُخزَّن ناتجه: استدعاء الوحدة مرتين يعيد نفس الكائن.

- الامتداد .js اختياري في require.

2. ES Modules (المعيار الحديث)

// math.mjs
export const add = (a, b) => a + b;
export default function multiply(a, b) { return a * b; }
// app.mjs
import multiply, { add } from "./math.mjs";   // الامتداد إلزامي
console.log(add(2, 3), multiply(2, 3));

لتفعيله لكل ملفات .js: أضف "type": "module" إلى package.json. مزاياه: نفس صيغة المتصفح، وawait في المستوى الأعلى مسموح، وتحليل ثابت (أدوات البناء تحذف الكود غير المستخدم).

| | CommonJS | ES Modules |

|---|---|---|

| التصدير | module.exports | export |

| الاستيراد | require() | import |

| await في المستوى الأعلى | ❌ | ✅ |

| __dirname | موجود | import.meta.dirname (Node 20.11+) |

للمشاريع الجديدة: ES Modules. ولا تخلط الاثنين في نفس الملف.

الوحدات المدمجة

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

console.log(path.join("uploads", "images", "a.png"));   // يستخدم فاصل النظام الصحيح
console.log(path.extname("report.pdf"));                // .pdf
console.log(os.cpus().length, "نواة");

البادئة node: توضح أنها وحدة مدمجة لا حزمة من npm. أشهرها: fs و path و http و crypto و events و os و url.

كيف يجد Node الوحدة؟

- ./ أو ../: ملف نسبي لمكان الملف الحالي.

- اسم بلا مسار (express): حزمة في node_modules (الدرس القادم).

- node:...: وحدة مدمجة.

تمرين

أنشئ utils/format.js يصدّر formatPrice(n) (مثلاً "1,500 د.ع") و slugify(text)، واستورده في app.js مرة بـ CommonJS ومرة بنسخة ES Modules (.mjs).

// مثال واحد يحاكي ملفين ليعمل مباشرة.
// في مشروع حقيقي: كل قسم في ملفه، مع module.exports و require.

// ===== math.js =====
const mathModule = (() => {
  const add = (a, b) => a + b;
  const subtract = (a, b) => a - b;
  const divide = (a, b) => {
    if (b === 0) throw new RangeError("لا يمكن القسمة على صفر");
    return a / b;
  };
  const secretHelper = () => "خاص بالوحدة — غير مصدَّر";
  return { add, subtract, divide };   // module.exports = { add, subtract, divide };
})();

// ===== app.js =====
// const { add, subtract, divide } = require('./math');
const { add, subtract, divide } = mathModule;

console.log("2 + 3 =", add(2, 3));
console.log("10 - 4 =", subtract(10, 4));
try {
  divide(5, 0);
} catch (err) {
  console.log("خطأ:", err.message);
}
console.log("secretHelper مُصدَّرة؟", "secretHelper" in mathModule);

// ===== الوحدات المدمجة =====
const path = require("node:path");
const os = require("node:os");
console.log(path.join("uploads", "2026", "avatar.png"));
console.log("الامتداد:", path.extname("report.final.pdf"));
console.log("نظام التشغيل:", os.platform());
اختبر فهمك