مديروا الحزم
💡 دليل التعلم: لكتابة الكود لا داعي لإعادة اختراع العجلة — 99% من الوظائف كتبها آخرون ونشروها على الإنترنت. مدير الحزم هو الأداة التي تساعدك في إيجاد وتحميل وإدارة تلك "القطع الجاهزة". يدور هذا الفصل حول سؤال محوري: كيف نجعل تبعيات الكود قابلة للتكرار والتعاون والصيانة؟
0. لماذا ستستخدم مدير حزم حتماً؟
تخيل أنك تريد كتابة برنامج Node.js يمكنه إرسال طلبات HTTP. أمامك طريقان:
- الطريقة أ (يدوية): تنفذ بنفسك اتصال TCP، وتحليل بروتوكول HTTP، ومعالجة إعادة التوجيه، وآلية المهلة... ربما آلاف الأسطر وأشهر من التصحيح.
- الطريقة ب (مدير حزم):
npm install axios، في عشر ثوانٍ وسطر واحد.
مدير الحزم هو في جوهره "متجر التطبيقات للكود". يساعدك في:
- إيجاد المكتبات التي نشرها آخرون في سجل مركزي (Registry)
- تنزيلها وتثبيتها تلقائياً في مشروعك
- إدارة تبعيات تلك المكتبات (تبعيات التبعيات)
- تسجيل النسخة الدقيقة التي تستخدمها لضمان عدم وجود مشاكل في عمل الفريق
1. نظرة عامة على مديري الحزم حسب النظام البيئي/اللغة
لغات البرمجة وأنظمة التشغيل المختلفة لها سلاسل أدوات خاصة، لكن المنطق الأساسي متطابق.
👇 جرّب: اختر النظام البيئي الذي تعرفه واستكشف أدواته الرئيسية.
npm install lodashnpm install -D typescriptnpm run buildnpm list --depth=0package.jsonProject manifest that records dependencies and scriptspackage-lock.jsonPins exact versions for consistent environmentsnode_modules/Directory where installed packages live1.1 من أين تُنزّل الحزم؟ — السجل (Registry)
كل نظام بيئي لديه سجل مركزي يخزن جميع الحزم المتاحة للتنزيل:
| النظام البيئي | السجل | عدد الحزم |
|---|---|---|
| JavaScript | npmjs.com | 2 مليون+ |
| Python | pypi.org | 500 ألف+ |
| Rust | crates.io | 150 ألف+ |
| Go | pkg.go.dev | 500 ألف+ |
| أدوات macOS/Linux | formulae.brew.sh | 7000+ |
| برامج Windows | winget.run / chocolatey.org | عشرات الآلاف |
1.2 مقارنة رواد JavaScript الثلاثة: npm vs yarn vs pnpm
وظائف مشابهة، والفروق بشكل رئيسي في السرعة واستخدام القرص:
استخدام القرص: pnpm (روابط صلبة مشتركة) < yarn PnP (بدون node_modules) < npm (نسخ كاملة)
سرعة التثبيت: pnpm ≈ yarn > npm
عادات الاستخدام: npm (الأكثر شيوعاً) > pnpm (موصى به للمشاريع الجديدة) > yarn (بعض الفرق)التوصية: استخدم pnpm في المشاريع الجديدة؛ حافظ على الأداة الحالية في المشاريع القائمة، دون تبديل عشوائي.
1.3 مقارنة رواد Windows الثلاثة: winget vs Chocolatey vs Scoop
| winget | Chocolatey | Scoop | |
|---|---|---|---|
| الدعم الرسمي | Microsoft رسمي | طرف ثالث | طرف ثالث |
| يحتاج مدير | جزئياً | نعم | لا |
| مناسب لـ | تثبيت البرامج اليومي | نشر المؤسسات الكبير | إدارة أدوات التطوير |
| عدد الحزم | كثير وينمو بسرعة | الأكثر (10000+) | مركز على أدوات التطوير |
التوصية: winget للاستخدام اليومي، scoop لأدوات التطوير، Chocolatey للأتمتة المؤسسية.
2. تثبيت حزمة — ماذا يحدث خلف الكواليس؟
تكتب npm install axios، يصمت سطر الأوامر لبضع ثوانٍ ثم ينتهي. ماذا حدث في تلك الثواني؟
👇 جرّب: اختر حزمة وانقر على "تشغيل" لمراقبة عملية التثبيت بالكامل.
{
"name": "my-project",
"version": "1.0.0",
"dependencies": {},
"devDependencies": {}
}2.1 المراحل الأربع بالتفصيل
① حل التبعيات (Resolve)
يقرأ المدير أولاً ما تريد تثبيته. مثلاً axios يعتمد على follow-redirects و form-data وغيرها، وهذه يجب تثبيتها أيضاً. هذه العملية تُسمى بناء شجرة التبعيات.
② التنزيل (Fetch)
تنزيل جميع الحزم المطلوبة من السجل (ملفات مضغوطة .tgz). المديرون الذكيون:
- ينزلون عدة حزم بالتوازي بدلاً من الانتظار واحداً تلو الآخر
- يفحصون ذاكرة التخزين المؤقت المحلية أولاً؛ إذا وُجدت لا يستخدمون الشبكة
③ الربط (Link)
فك ضغط الحزم المنزّلة ووضعها في دليل node_modules/ ومعالجة علاقات المرجعية.
④ كتابة ملف القفل (Lockfile)
تسجيل أرقام النسخ الدقيقة لهذا التثبيت في package-lock.json (أو yarn.lock / pnpm-lock.yaml).
2.2 مرجع سريع للأوامر الأكثر استخداماً
# ── JavaScript (npm) ──────────────────────────────────
npm install # تثبيت جميع التبعيات حسب package.json
npm install axios # تثبيت حزمة جديدة (تبعية إنتاج)
npm install -D jest # تثبيت تبعية تطوير (فقط أثناء التطوير)
npm install -g tsx # تثبيت عام (متاح في أي مجلد)
npm uninstall axios # إلغاء تثبيت الحزمة
npm update # ترقية جميع الحزم للنسخة المتوافقة الأحدث
npm run build # تشغيل السكربتات في package.json
npx create-react-app . # تشغيل مؤقت دون تثبيت في المشروع
# ── Python (pip) ──────────────────────────────────────
pip install requests # تثبيت حزمة
pip install requests==2.28.0 # تثبيت نسخة محددة
pip freeze > requirements.txt # تصدير قائمة التبعيات الحالية
pip install -r requirements.txt # تثبيت حسب القائمة
# ── Rust (cargo) ──────────────────────────────────────
cargo add serde # إضافة تبعية (يُحدّث Cargo.toml تلقائياً)
cargo build # بناء المشروع
cargo test # تشغيل الاختبارات
cargo run # تشغيل المشروع
# ── Go (go mod) ───────────────────────────────────────
go get github.com/gin-gonic/gin # إضافة تبعية
go mod tidy # تنظيف التبعيات
go build ./... # بناء
# ── Windows (winget) ──────────────────────────────────
winget install Git.Git # تثبيت برنامج
winget upgrade --all # تحديث جميع البرامج المثبتة2.3 ما هي npm scripts؟
يوجد في package.json حقل scripts وهو مشغّل المهام المدمج في npm:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"test": "jest",
"lint": "eslint src/"
}
}طريقة التشغيل: npm run dev، npm run build. الفوائد:
- مدخل موحد: أعضاء الفريق لا يحتاجون لحفظ الأوامر المحددة لكل أداة
- تهيئة تلقائية للبيئة: عند التشغيل يُضاف
node_modules/.binتلقائياً إلى PATH
3. التثبيت العام مقابل التثبيت المحلي
هذا من أكثر المفاهيم إرباكاً للمبتدئين.
3.1 الفروقات
npm install axios # محلي: يُثبّت في ./node_modules/، فقط المشروع الحالي يمكنه استخدامه
npm install -g typescript # عام: يُثبّت في دليل النظام، أي مشروع/مجلد يمكنه استخدامه| التثبيت المحلي | التثبيت العام | |
|---|---|---|
| الموقع | ./node_modules/ | دليل على مستوى النظام (مثل /usr/local/lib/) |
| مناسب لـ | مكتبات يعتمد عليها المشروع (axios, vue, react) | أدوات CLI (tsc, eslint, create-react-app) |
| عزل النسخ | كل مشروع بنسخة مستقلة ✅ | نسخة واحدة مشتركة على كل الجهاز ⚠️ |
| اتساق الفريق | ملف القفل يضمن الاتساق ✅ | قد تختلف النسخة لدى كل شخص ⚠️ |
3.2 القاعدة الذهبية
تبعيات المكتبات (axios, lodash, vue) تُثبّت دائماً محلياً؛ أدوات CLI (tsc, eslint) يُفضل تثبيتها محلياً واستدعاؤها بـ
npx.
لماذا يُنصح بتثبيت أدوات CLI محلياً أيضاً؟
إذا ثبّتَ eslint@8 عاماً، لكن المشروع أ يحتاج قواعد eslint@9 الجديدة، عليك التبديل بين العام والمشروع. ثبّت eslint محلياً واستخدم npx eslint .، وسيتمكن كل مشروع من تهيئة نسخته الخاصة بشكل مستقل.
3.3 npx — تشغيل مؤقت دون تلويث البيئة
npx هو مشغّل حزم مدمج في npm يتيح لك تشغيل حزمة دون تثبيتها:
# دون تثبيت create-vue، شغّله مباشرة لتهيئة مشروع
npx create-vue my-project
# دون تثبيت prettier، نسّق الملفات مباشرة
npx prettier --write src/
# إجبار استخدام نسخة محددة (تجاهل المثبتة)
npx typescript@5.4 tsc --versionPython عبر uvx وRust عبر cargo run يوفران قدرة "التشغيل المؤقت" المشابهة:
uvx ruff check . # Python: تشغيل مؤقت لفاحص ruff
cargo install ripgrep # Rust: تثبيت عام، يصبح أمر النظام rg4. سر أرقام النسخ — الإصدار الدلالي
ستجد في package.json محتوى مثل:
{
"dependencies": {
"axios": "^1.6.8",
"typescript": "~5.4.0"
}
}ماذا يعني ^ و ~؟
👇 جرّب: مرر المؤشر فوق أجزاء رقم النسخ لفهم معانيها؛ انقر على رموز النطاق لمعرفة أي النسخ ستُقبل.
^2.8.3~2.8.32.8.3*4.1 لماذا لا نُثبّت النسخة بالضبط؟
| النهج | الميزة | العيب |
|---|---|---|
"axios": "1.6.8" (تثبيت دقيق) | قابل للتنبؤ تماماً | تصحيحات الأمان لا تُحدّث تلقائياً |
"axios": "^1.6.8" (نطاق متوافق، موصى به) | يحصل تلقائياً على إصلاحات الأخطاء والميزات الجديدة | نادراً قد يُدخل عدم توافق بسيط |
"axios": "*" (أي نسخة) | دائماً الأحدث | ترقية النسخة الرئيسية قد تُكسر الكود تماماً |
أفضل ممارسة: أعلن عن النطاق بـ ^ + ملف القفل لتثبيت النسخة الفعلية، واستخدمهما معاً.
4.2 ما هو "جحيم التبعيات"؟
عندما تعتمد على 50 حزمة وكل حزمة تعتمد على عدة أخرى، قد يكون "شجرة التبعيات" مئات العقد. إذا حزمتان تعتمدان على نسخ غير متوافقة من نفس المكتبة، ينشأ "تعارض تبعيات".
حلول كل نظام بيئي:
- npm v3+: يرفع للقمة النسخ من نفس النسخة الرئيسية؛ نسخ رئيسية مختلفة تُثبّت كل على حدة
- pnpm: روابط صلبة + عزل صارم، يمنع "التبعيات الوهمية" (حزم غير مُعلن عنها لكنها متاحة)
- cargo (Rust): على مستوى اللغة، كل حزمة تعتمد على نسخة واحدة فقط، متجنباً التعارضات تماماً
- go mod (Go): استراتيجية اختيار النسخة الدنيا (MVS)، يختار أقل نسخة تُرضي جميع القيود
5. ملف القفل — حجر الزاوية للتعاون الجماعي
5.1 لماذا نحتاج ملف قفل؟
لنفترض أن package.json يقول "axios": "^1.6.0":
- أنت تثبت اليوم ← تحصل على
1.6.8 - زميلك يثبت غداً ← قد يحصل على
1.7.0(نُشرت الليلة الماضية) - خادم CI الأسبوع القادم ← قد يحصل على
1.7.1
نفس الكود، ثلاثة نتائج مختلفة. ملف القفل يسجل النسخة الدقيقة لكل حزمة؛ الجميع يثبتون بناءً عليه والنتيجة متطابقة.
| السيناريو | الأمر | السلوك |
|---|---|---|
| مزامنة بيئة التطوير | npm install | يراعي ملف القفل، لا يُرقّي النسخ |
| CI / نشر الإنتاج | npm ci | يثبّت بصرامة حسب ملف القفل؛ إذا وُجد اختلاف يُبلغ عن خطأ |
| ترقية النسخ يدوياً | npm update | يُرقّي ضمن النطاق المسموح ويُحدّث ملف القفل |
5.2 هل يجب رفع ملف القفل إلى Git؟
التطبيقات يجب رفعه، المكتبات المنشورة على npm قد لا تحتاج.
- ✅ تطبيقات الويب، خدمات الخلفية: يجب رفعه لضمان تطابق التطوير والإنتاج
- ❌ المكتبات المنشورة على npm: عادةً لا تُرفع؛ مستخدمو المكتبة لديهم ملفات قفل خاصة
- ✅ مشاريع Python:
requirements.txtيعمل كملف قفل في حد ذاته ويجب رفعه - ✅ مشاريع Go:
go.sumيجب رفعه للتحقق من السلامة
6. البيئات الافتراضية في Python
Python لديها مفهوم يستحق اهتماماً خاصاً: البيئة الافتراضية (venv).
لماذا نحتاجها؟
Python يثبّت الحزم عاماً بشكل افتراضي. مشروعك أ يحتاج requests==2.28، ومشروعك ب يحتاج requests==2.31؛ كلاهما سيتعارض.
الحل: إنشاء بيئة افتراضية مستقلة لكل مشروع، دون تداخل.
# 1. إنشاء بيئة افتراضية (نفّذ في جذر المشروع)
python -m venv .venv
# 2. تفعيل البيئة الافتراضية
source .venv/bin/activate # macOS / Linux
.venv\Scripts\activate # Windows (CMD)
.venv\Scripts\Activate.ps1 # Windows (PowerShell)
# 3. بعد التفعيل، pip install تؤثر فقط على البيئة الافتراضية الحالية
pip install requests
# 4. الخروج من البيئة الافتراضية
deactivate⚠️ مشكلة شائعة على Windows: PowerShell يمنع تشغيل السكربتات افتراضياً؛ نفّذ أولاً:
powershellSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
البدائل الحديثة:
conda create -n myproject python=3.11— تدير حتى نسخة Python نفسهاuv venv && source .venv/bin/activate— مكتوبة بـ Rust، سرعة إنشاء فائقة
هل يجب رفع .venv إلى Git؟
لا! .venv يُنشأ محلياً ويجب إضافته إلى .gitignore. استخدم requirements.txt أو pyproject.toml لوصف التبعيات.
7. مرجع سريع للأسئلة الشائعة
س: هل يجب رفع node_modules إلى Git؟
لا! عادةً يزن مئات الميغابايت ويجب إضافته إلى .gitignore. مع package-lock.json يمكن لأي شخص إعادة البناء بسرعة عبر npm install.
س: ماذا أفعل عند فشل التثبيت / ظهور أخطاء غريبة؟
# مسح ذاكرة التخزين المؤقت، حذف التثبيت القديم، إعادة المحاولة
npm cache clean --force
rm -rf node_modules package-lock.json # macOS/Linux
rmdir /s /q node_modules && del package-lock.json # Windows CMD
npm installس: التثبيت بطيء جداً؟
# التبديل لمرآة محلية (يُنصح بالكتابة في ملف .npmrc)
echo "registry=https://registry.npmmirror.com" > .npmrc
# pip يمكن أيضاً تهيئة مرآة
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simpleس: ماذا أفعل إذا كانت الحزمة بها ثغرات أمنية؟
npm audit # فحص الثغرات المعروفة
npm audit fix # إصلاح تلقائي للثغرات المتوافقة
npm audit fix --force # ترقية إجبارية (قد تكون مدمرة، استخدم بحذر)س: كيف أعرف أن حزمة ما موثوقة؟
على npmjs.com أو bundlephobia.com تحقق من:
- التنزيلات الأسبوعية (كلما زادت، زادت الموثوقية)
- آخر تحديث (أكثر من سنتين بدون تحديث، كن حذراً)
- عدد التبعيات (كلما زادت، زاد احتمال إدخال مشاكل)
- نجوم GitHub ونشاط المشكلات
س: أين تُثبّت برامج winget على Windows؟
winget يثبّت افتراضياً في دليل النظام (يحتاج مدير) أو %LOCALAPPDATA%\Microsoft\WindowsApps. Scoop يثبّت البرامج في %USERPROFILE%\scoop\apps\ بشكل موحد، مما يُسهّل الإدارة والنقل.
8. جدول مرجعي للمصطلحات
| المصطلح بالإنجليزية | الترجمة | الشرح |
|---|---|---|
| Package | حزمة / مكتبة | وحدة كود كتبها آخرون ونشروها |
| Registry | سجل / مستودع | خادم تخزين مركزي لجميع الحزم (مثل npmjs.com) |
| Dependency | تبعية | حزم أخرى يحتاجها مشروعك للعمل |
| devDependency | تبعية تطوير | حزم تحتاجها فقط في مرحلة التطوير (أطر الاختبار، أدوات البناء، إلخ) |
| Lockfile | ملف قفل | يسجل أرقام النسخ الدقيقة لضمان اتساق البيئة |
| SemVer | الإصدار الدلالي | اتفاقية تسمية النسخ MAJOR.MINOR.PATCH |
| node_modules | دليل الوحدات | الدليل الذي يخزن فيه npm الحزم المثبتة فعلياً |
| venv | بيئة افتراضية | بيئة عزل حزم مستقلة لمشاريع Python |
| tarball | ملف مضغوط | صيغة توزيع الحزم، عادةً ملف .tgz |
| Hoisting | الرفع | npm يرفع التبعيات الفرعية للمستوى الأعلى لتجنب التثبيت المكرر |
| Phantom Dependency | تبعية وهمية | حزم غير مُعلن عنها في ملف التهيئة لكنها قابلة للاستخدام (pnpm يمنعها) |
| npx | — | مشغّل حزم مدمج في npm، يشغّل الحزم مؤقتاً دون تثبيتها |
| go.sum | — | ملف تحقق hash لوحدات Go، يمنع العبث بالتبعيات |
| Crate | — | اسم وحدة "الحزمة" في نظام Rust البيئي |
| winget | — | مدير حزم Windows الرسمي (مدمج في Windows 10/11) |
الخلاصة: جوهر مديري الحزم
تذكر الجوهر في أربع جمل:
- مدير الحزم = متجر تطبيقات: يساعدك في إيجاد وتثبيت وإدارة قطع الكود دون إعادة اختراع العجلة.
- ملف القفل = عقد الفريق: يُثبّت النسخ الدقيقة، ويجعل "يعمل على جهازي" شيئاً من الماضي.
- الإصدار الدلالي = لغة تواصل:
^يحصل على التحديثات بأمان؛ عندما يتغير MAJOR، كن حذراً. - محلي > عام: تبعيات المشروع تُثبّت محلياً قدر الإمكان؛ استخدم
npx/uvxللأدوات المؤقتة للحفاظ على بيئة نظيفة.