Node.js: مقدمة إلى Node.js

أليس مطورة برمجيات «الخلفية». كانت شركتها بحاجة إلى «بناء» واجهة برمجة تطبيقات REST للخلفية لتطبيق جوال في غضون أسبوعين. كان الفريق يتألف بالكامل من مطوري «الواجهة الأمامية» الذين لا يجيدون سوى لغة JavaScript، ولم يكن أحد منهم على استعداد لتخصيص وقت لتعلم لغة برمجة جديدة. حتى أن مدير المشروع فكر في توظيف مطور لغة Python، لكن الوقت لم يكن كافياً ببساطة. وبينما بدأ الفريق يشعر بالقلق، اكتشفت أليس Node.js — وهو بيئة تشغيل تعمل بلغة JavaScript على الخادم. تمكن مطورو الواجهة الأمامية من كتابة واجهات برمجة التطبيقات الخلفية باستخدام الصيغة التي كانوا على دراية بها بالفعل، وتم إطلاق المشروع بنجاح بعد أسبوعين. أدرك أليس من خلال ذلك أن Node.js ليست مجرد أداة — بل هي جسر يربط بين الواجهة الأمامية والواجهة الخلفية.

ستتعلم:


1. ما هو Node.js؟

(1) التعريف

Node.js هي بيئة تشغيل لـ JavaScript تستند إلى محرك Chrome V8. وهي تتيح تشغيل JavaScript مباشرةً على الخادم، بشكل مستقل عن المتصفح. Node.js ليست لغة برمجة جديدة ولا إطار عمل، بل هي منصة لتنفيذ JavaScript من جانب الخادم.

(2) خلفية نشأتها

في عام 2009، أنشأ رايان دال Node.js استنادًا إلى محرك V8. وكان هدفه الأصلي هو حل مشكلة الحجب الناتجة عن عمليات الإدخال/الإخراج من جانب الخادم — حيث تقوم خوادم الويب التقليدية بحجب الخيوط عند معالجة عمليات الإدخال/الإخراج مثل قراءة الملفات وطلبات الشبكة، في حين يستخدم Node.js نهجًا قائمًا على الأحداث، مما يسمح لخيط واحد بمعالجة عدد كبير من الاتصالات المتزامنة بكفاءة.

▶ مثال: أول برنامج نصي لك بلغة Node.js

إنشاء الملف hello.js:

JAVASCRIPT
console.log('Hello, Node.js!');
console.log('Node.js version:', process.version);
console.log('Platform:', process.platform);
▶ جرّب الكود

قم بتشغيل الأمر التالي في المحطة الطرفية:

BASH
node hello.js

النتيجة المتوقعة:

TEXT 📖 للعرض فقط
Hello, Node.js!
Node.js version: v20.11.0
Platform: win32


2. محرك V8 وبنية Node.js

(1) دور محرك V8

V8 هو محرك لغة جافا سكريبت طورته شركة جوجل، ويقوم بتحويل كود جافا سكريبت إلى كود آلي لتنفيذه. ويأتي محرك V8 مدمجًا بشكل مباشر في Node.js، وهذا هو السبب وراء الأداء العالي الذي يقدمه. وتتيح تقنية التحويل «في الوقت المناسب» (JIT) الخاصة بـ V8 تشغيل جافا سكريبت بسرعات تقترب من سرعات الكود الأصلي.

(2) طبقات بنية Node.js

تنقسم بنية Node.js إلى أربع طبقات من الأسفل إلى الأعلى:

المستوى التكوين الوظيفة
طبقة كود جافا سكريبت ملفات .js التي يكتبها المستخدم منطق الأعمال
طبقة واجهة برمجة تطبيقات Node.js وحدات مثل fs وhttp وpath توفر إمكانيات من جانب الخادم
طبقة ربط Node.js كود الجسر بلغة C++ ربط JavaScript بمكتبة C الأساسية
المكتبات ذات المستوى المنخفض V8، libuv، OpenSSL، وغيرها المحركات ونداءات النظام

(3) الدور الرئيسي لمكتبة libuv

libuv هي مكتبة الإدخال/الإخراج غير المتزامن لـ Node.js، وتوفر حلقة أحداث، ومجموعة خيوط، وتجريدًا متعدد المنصات لعمليات الإدخال/الإخراج غير المتزامنة. وهي تمكّن Node.js من معالجة العمليات غير المتزامنة — مثل عمليات الإدخال/الإخراج للملفات، وعمليات الشبكة، والمؤقتات — بطريقة متسقة عبر أنظمة التشغيل المختلفة.

▶ مثال: عرض معلومات التبعيات في Node.js

JAVASCRIPT
console.log('V8 version:', process.versions.v8);
console.log('libuv version:', process.versions.libuv);
console.log('OpenSSL version:', process.versions.openssl);
console.log('Node.js version:', process.version);
▶ جرّب الكود

الناتج:

TEXT 📖 للعرض فقط
V8 version: 11.3.244.8
libuv version: 1.46.0
OpenSSL version: 3.0.12
Node.js version: v20.11.0

▶ مثال:(4) مخطط الهندسة المعمارية

100%
graph TB
    A["JavaScript Code<br/>(User-written .js Documents)"] --> B["Node.js API<br/>(fs / http / path / ...)"]
    B --> C["Node.js Bindings<br/>(C++ Bridge Layer)"]
    C --> D1["V8 Engine<br/>(JavaScript Compile and Run)"]
    C --> D2["libuv<br/>(Event Loop + Asynchronous I/O)"]
    C --> D3["Other C Libs<br/>(OpenSSL / zlib / c-ares)"]
    D2 --> E["Operating System<br/>(Documents / Internet / Process)"]


3. عمليات الإدخال/الإخراج (I/O) التي تعمل استجابةً للأحداث وغير المعطلة

(1) النموذج القائم على الأحداث

يستخدم Node.js بنية قائمة على الأحداث: حيث يستجيب البرنامج للعمليات المختلفة عن طريق تسجيل دالات الاستدعاء المرتبطة بالأحداث، بدلاً من إجراء عمليات الاستقصاء بشكل نشط. وعند اكتمال عملية الإدخال/الإخراج، تضع حلقة الأحداث دالة الاستدعاء المقابلة في قائمة انتظار حتى يحين وقت تنفيذها.

(2) معنى الإدخال/الإخراج غير المعطل

تقوم الخوادم التقليدية بحظر مؤشر الترابط الحالي أثناء قراءة الملف حتى يتم قراءة الملف بالكامل. أما Node.js فتعود فور بدء طلب الإدخال/الإخراج، وتواصل تنفيذ التعليمات البرمجية التالية، ثم تعالج النتيجة عبر استدعاء مرتد بمجرد اكتمال عملية الإدخال/الإخراج. ويتيح هذا النهج لمؤشر ترابط واحد معالجة مئات الطلبات المتزامنة في آن واحد.

(3) مقدمة إلى حلقة الأحداث

تُعد حلقة الأحداث آلية الجدولة الأساسية في Node.js، والتي تعمل في حلقة متكررة تمر بالمراحل التالية:

  1. الساعات: تنفيذ دالة الاستدعاء setTimeout / setInterval
  2. عمليات الاستدعاء المعلقة: عمليات الاستدعاء التي تُنفِّذ عمليات نظامية
  3. الوضع الخامل، الاستعداد: للاستخدام الداخلي
  4. poll: يسترد أحداث الإدخال/الإخراج الجديدة وينفذ إجراءات الاستدعاء المرتبطة بالإدخال/الإخراج
  5. تحقق: تنفيذ دالة الاستدعاء setImmediate
  6. دوال الاستدعاء عند الإغلاق: تنفيذ دوال الاستدعاء الخاصة بأحداث الإغلاق

▶ مثال: قراءة الملفات بطريقة «الحجب» مقابل «عدم الحجب»

وضع الحجب (غير موصى به):

JAVASCRIPT
const fs = require('fs');
const data = fs.readFileSync('/etc/hosts', 'utf8');
console.log('File read (blocking):', data.length, 'bytes');
console.log('This line runs after file is read');
▶ جرّب الكود

الوضع غير المعطل (موصى به):

JAVASCRIPT
const fs = require('fs');
fs.readFile('/etc/hosts', 'utf8', (err, data) => {
  if (err) throw err;
  console.log('File read (non-blocking):', data.length, 'bytes');
});
console.log('This line runs immediately');

الإخراج (الوضع غير المعطل):

TEXT 📖 للعرض فقط
This line runs immediately
File read (non-blocking): 250 bytes

لاحظ أنه في الوضع غير المعطل، تُطبع العبارة «يتم تنفيذ هذا السطر على الفور» أولاً، مما يشير إلى أن readFile لم يوقف تنفيذ الكود اللاحق.



4. Node.js مقابل جافا سكريبت في المتصفح

(1) الاختلافات الرئيسية

يستخدم كل من Node.js وJavaScript في المتصفح نفس مواصفات اللغة (ECMAScript)، لكن بيئات التشغيل الخاصة بهما وواجهات برمجة التطبيقات (API) المتاحة تختلف تمامًا.

معايير المقارنة Node.js جافا سكريبت في المتصفح
بيئة التشغيل الخادم المتصفح
نظام الوحدات CommonJS / ESM ESM
كائن عام عام / عملية نافذة / مستند
نظام الملفات الوصول المباشر عبر وحدة fs لا يمكن الوصول إليه مباشرة
إدخال/إخراج الشبكة وحدات http / net fetch / XMLHttpRequest
معالجة DOM بدون DOM واجهة برمجة تطبيقات DOM
مدير الحزم npm لا شيء (أو عبر CDN)
الاستخدامات الرئيسية تطبيقات الخادم، أدوات واجهة الأوامر (CLI) التفاعلات عبر الويب، عرض واجهة المستخدم

(2) أوجه التشابه

▶ مثال: نفس الصيغة، واجهات برمجة تطبيقات مختلفة

كود المتصفح:

JAVASCRIPT
document.getElementById('output').textContent = 'Hello from browser';
▶ جرّب الكود

كود Node.js:

JAVASCRIPT
const fs = require('fs');
fs.writeFileSync('output.txt', 'Hello from Node.js');

تبقى صيغة لغة جافا سكريبت كما هي، لكن الكائنات التي يتم التعامل معها مختلفة تمامًا: فالمتصفحات تتعامل مع نموذج DOM، بينما يتعامل Node.js مع نظام الملفات.



5. حالات الاستخدام النموذجية لـ Node.js

(1) خدمة واجهة برمجة التطبيقات REST

يُعد Node.js خيارًا مناسبًا تمامًا لإنشاء واجهات برمجة التطبيقات (API) التي تعمل وفقًا لمعيار REST. ونظرًا لأن نموذج الإدخال/الإخراج (I/O) غير المعطل الخاص به يتعامل بكفاءة مع العديد من الطلبات المتزامنة، ولأن JSON هو تنسيق البيانات الأصلي في JavaScript، فإن ذلك يزيل العبء الإضافي الناجم عن التسلسل.

(2) أدوات واجهة سطر الأوامر

تعد Webpack وBabel وESLint وnpm أدوات CLI تم إنشاؤها باستخدام Node.js. ويوفر Node.js مجموعة غنية من واجهات برمجة التطبيقات (APIs) للتعامل مع نظام الملفات، والعمليات الفرعية، ووسائط سطر الأوامر.

(3) التطبيقات التي تعمل في الوقت الفعلي

تتطلب سيناريوهات مثل أنظمة الدردشة، والتعاون عبر الإنترنت، والإشعارات في الوقت الفعلي، اتصالات مستمرة وثنائية الاتجاه. ويُعد دعم WebSocket في Node.js وبنيته القائمة على الأحداث مناسبين بشكل طبيعي لتلبية هذه الاحتياجات.

(4) الخدمات الصغيرة

يتميز Node.js بسرعة التشغيل واستهلاكه القليل للذاكرة، مما يجعله خيارًا مثاليًّا للخدمات الصغيرة خفيفة الوزن. ويمكن نشر كل خدمة صغيرة وتوسيع نطاقها بشكل مستقل.

(5) الزحف على الويب وجمع البيانات

عند دمج Node.js مع مكتبات مثل Cheerio، يمكنه الزحف إلى بيانات الويب وتحليلها بكفاءة، كما أن عمليات الإدخال/الإخراج غير المتزامنة تجعل الطلبات المتزامنة فعالة للغاية.

▶ مثال: مقارنة بين حالات الاستخدام

السيناريو المزايا المشاريع النموذجية
واجهة برمجة التطبيقات REST عمليات الإدخال/الإخراج غير المعطلة + JSON الأصلي Express / Fastify / Koa
أدوات CLI عمليات الملفات + العمليات الفرعية Webpack / Babel / ESLint
التطبيقات في الوقت الفعلي WebSocket + قائمة على الأحداث Socket.IO / ws
الخدمات الصغيرة خفيفة الوزن + سريعة الإعداد NestJS / Seneca
استخراج البيانات من الويب التزامن غير المتزامن + تحليل DOM Puppeteer / Cheerio

▶ مثال: إنشاء خادم HTTP في 5 أسطر من التعليمات البرمجية

JAVASCRIPT
const http = require('http');
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ message: 'Hello from Node.js API' }));
});
server.listen(3000, () => console.log('Server running on port 3000'));
▶ جرّب الكود
BASH
node server.js
TEXT 📖 للعرض فقط
Server running on port 3000

تفضل بزيارة http://localhost:3000 للاطلاع على استجابة JSON.



6. سياسة إصدارات Node.js

(1) LTS والإصدار الحالي

يستخدم Node.js استراتيجية إصدار ثنائية المسار:

المقارنة LTS (الدعم طويل الأمد) الإصدار الحالي
دورة الإصدار إصدار رئيسي واحد كل سنتين إصدار رئيسي واحد كل 6 أشهر
فترة الصيانة 30 شهراً حوالي 6 أشهر
الاستقرار عالي؛ لا يتضمن سوى إصلاحات الأخطاء والتحديثات الأمنية منخفض؛ يتضمن أحدث الميزات
حالات الاستخدام بيئة الإنتاج تجربة الميزات الجديدة، والاختبار
قواعد ترقيم الإصدارات الأرقام الزوجية (18، 20، 22...) الأرقام الفردية (19، 21، 23...)

(2) توصيات بشأن اختيار الإصدار

(3) أدوات التحكم في الإصدارات

نوصي باستخدام nvm (مدير إصدارات Node) لإدارة إصدارات Node.js والتبديل بينها.

▶ مثال: إدارة الإصدارات باستخدام nvm

BASH
nvm install 20
nvm use 20
nvm ls
TEXT 📖 للعرض فقط
       v18.17.0
->     v20.11.0
         system
default -> 20 (-> v20.11.0)

▶ مثال: التحقق من إصدار Node.js الحالي وحالته

BASH
node -v
node -e "console.log(process.release.lts ? 'LTS: ' + process.release.lts : 'Current (non-LTS)')"
TEXT 📖 للعرض فقط
v20.11.0
LTS: Iron


❓ أسئلة شائعة

س هل Node.js لغة برمجة جديدة؟
ج لا. Node.js هي بيئة تشغيل لـ JavaScript تتيح تشغيل JavaScript على جانب الخادم؛ أما اللغة نفسها فهي لا تزال JavaScript.
س لماذا يُعد Node.js مناسبًا للتطبيقات التي تعتمد بشكل مكثف على عمليات الإدخال/الإخراج؟
ج يستخدم Node.js نموذجًا لعمليات الإدخال/الإخراج قائمًا على الأحداث وغير معطل، مما يسمح لخيط واحد بمعالجة عدد كبير من طلبات الإدخال/الإخراج المتزامنة في الوقت نفسه دون تعطيل العملية بأكملها بسبب عملية واحدة بطيئة.
س ما هي المهام التي لا يناسبها Node.js؟
ج المهام التي تتطلب استخدامًا مكثفًا لوحدة المعالجة المركزية (CPU)، مثل ترميز الفيديو، والحسابات الرياضية المعقدة، ومعالجة الصور. يؤدي الاستخدام المطول لوحدة المعالجة المركزية إلى تعطيل حلقة الأحداث، مما يؤدي إلى وضع جميع الطلبات في قائمة الانتظار. وينبغي معالجة هذه الأنواع من المهام بواسطة خيوط العمل (worker threads) أو الخدمات الخارجية.
س هل يجب عليّ تعلم لغة جافا سكريبت قبل أن أتمكن من تعلم Node.js؟
ج نعم. Node.js ليست لغة جديدة بحد ذاتها؛ فهي تعمل بلغة جافا سكريبت. عليك إتقان أساسيات بناء الجمل في جافا سكريبت، والوظائف، والكائنات، والبرمجة غير المتزامنة (Promises / async-await) قبل أن تتمكن من استخدام Node.js بفعالية.
س ما الفرق بين Node.js و Deno؟
ج Deno هو أيضًا بيئة تشغيل لـ JavaScript/TypeScript، أنشأه رايان دال، المطور الأصلي لـ Node.js. أهم الاختلافات: يدعم Deno لغة TypeScript بشكل أصلي، ويستخدم ES Modules بدلاً من CommonJS، ويحتوي على بيئة آمنة (تعمل على تعطيل الوصول إلى الملفات والشبكة بشكل افتراضي)، ولا يتطلب وجود دليل package.json أو node_modules، ويتضمن أدوات تنسيق واختبار مدمجة في مكتبته القياسية. لا يزال نظام Deno البيئي في طور النمو، في حين أن نظام Node.js البيئي أكثر نضجًا.
س هل Node.js يعمل بخيط واحد؟
ج يعمل كود JavaScript في خيط واحد، لكن Node.js يستخدم مجموعة خيوط libuv (4 خيوط بشكل افتراضي) في الخلفية لمعالجة عمليات الإدخال/الإخراج للملفات، وعمليات البحث في نظام أسماء النطاقات (DNS)، وغيرها من العمليات. كما أنه يدعم خيوط العمل (worker threads) لمعالجة المهام التي تتطلب استخدامًا مكثفًا لوحدة المعالجة المركزية (CPU).
س ما الذي أحتاج إلى تثبيته لتعلم Node.js؟
ج ما عليك سوى تثبيت Node.js (الذي يأتي مزودًا بمدير الحزم npm) ومحرر أكواد (نوصي باستخدام VS Code). بعد التثبيت، قم بتشغيل node -v في نافذة الأوامر للتحقق من أنه يعمل.

📖 ملخص


📝 تمارين

  1. قم بتثبيت Node.js (يُنصح باستخدام الإصدار LTS)، ثم قم بتشغيل الأمر node -v للتحقق من نجاح التثبيت، وقم بتدوين رقم الإصدار الخاص بك وما إذا كان إصدار LTS أم لا.
  2. أنشئ ملفًا باسم hello.js، واستخدم console.log لعرض اسمك ورقم إصدار Node.js، ثم قم بتشغيله، والتقط لقطة شاشة
  3. اكتب برنامجًا نصيًّا يستخدم الكائن process لعرض المعلومات التالية: إصدار Node.js، ومنصة نظام التشغيل، ودليل العمل الحالي، وبنية وحدة المعالجة المركزية.
  4. استخدم fs.readFile لقراءة ملف نصي في الوضع غير المعطل وعرض محتوياته، ثم لاحظ ترتيب تنفيذ دوال الاستدعاء
  5. قارن بين fs.readFileSync (حجب) وfs.readFile (غير حجب) عن طريق طباعة الطوابع الزمنية قبل وبعد استدعاء الدالة المرتدة، على التوالي، أثناء قراءة الملف نفسه، لتوضيح الفرق في طريقة تنفيذهما.


7. مثال شامل: برنامج نصي لقراءة معلومات النظام

يستخدم البرنامج النصي التالي الوحدات المدمجة في Node.js لقراءة معلومات النظام وعرضها، مما يوضح القدرات الأساسية لـ Node.js كبيئة تشغيل من جانب الخادم:

JAVASCRIPT
const os = require('os');
const fs = require('fs');
const path = require('path');

const sysInfo = {
  nodeVersion: process.version,
  platform: process.platform,
  arch: process.arch,
  hostname: os.hostname(),
  totalMemoryMB: Math.round(os.totalmem() / 1024 / 1024),
  freeMemoryMB: Math.round(os.freemem() / 1024 / 1024),
  cpuCores: os.cpus().length,
  cpuModel: os.cpus()[0].model,
  uptimeHours: (os.uptime() / 3600).toFixed(2),
  cwd: process.cwd(),
  homedir: os.homedir()
};

const output = JSON.stringify(sysInfo, null, 2);
console.log(output);

const filePath = path.join(os.homedir(), 'nodejs-sysinfo.txt');
fs.writeFile(filePath, output, 'utf8', (err) => {
  if (err) {
    console.error('Write failed:', err.message);
    return;
  }
  console.log('System info saved to:', filePath);
});

النتيجة المتوقعة:

TEXT 📖 للعرض فقط
{
  "nodeVersion": "v20.11.0",
  "platform": "win32",
  "arch": "x64",
  "hostname": "DESKTOP-ABC123",
  "totalMemoryMB": 16384,
  "freeMemoryMB": 8192,
  "cpuCores": 8,
  "cpuModel": "Intel(R) Core(TM) i7-12700K",
  "uptimeHours": "48.32",
  "cwd": "C:\\projects\\node-demo",
  "homedir": "C:\\Users\\Alice"
}
System info saved to: C:\Users\Alice\nodejs-sysinfo.txt

يوضح هذا البرنامج النصي ثلاث قدرات أساسية لـ Node.js: استرداد معلومات نظام التشغيل (os)، والكتابة إلى ملف (fs)، ومعالجة المسارات (path). كما يستخدم البرنامج الإدخال/الإخراج غير المعطل (non-blocking I/O) للكتابة إلى ملف — حيث يتم تنفيذ استدعاء الرد (callback) الخاص بـ fs.writeFile بعد console.log، مما يوضح الطبيعة القائمة على الأحداث لـ Node.js.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%