ما هو npm؟ دليل شامل لمدير حزم Node.js للمبتدئين

دقائق القراءة: 10

في عالم تطوير الويب الحديث، أصبح Node.js ركيزة أساسية لا غنى عنها منذ ظهوره في عام 2009. لقد ساهم في بناء مئات الآلاف من الأنظمة والتطبيقات، مما دفع مجتمع المطورين إلى القول بأن “جافاسكريبت تلتهم البرمجيات”. لكن وراء هذا النجاح الباهر، يقف رفيق لا يقل أهمية: npm، أو مدير حزم Node.js. إنه الأداة التي مكنت مطوري JavaScript من مشاركة الحزم المفيدة مثل lodash و moment بسرعة وسهولة، مما أحدث ثورة في طريقة بناء المشاريع.

تخيل أن npm ليس مجرد أداة، بل هو محرك ضخم يدفع الابتكار في عالم JavaScript. حتى لحظة كتابة هذا الدليل، سهّل npm نشر أكثر من 1.3 مليون حزمة، بمعدل تنزيلات أسبوعي يتجاوز 16 مليار تنزيل! هذه الأرقام مذهلة وتؤكد على الدور المحوري الذي يلعبه npm في المنظومة التقنية. لذا، دعنا نتعمق في فهم ماهية npm وكيف يمكننا استغلال قوته.

ما هو npm؟ فهم مدير حزم Node.js

npm، وهو اختصار لـ “مدير حزم Node” (Node Package Manager)، هو المدير الافتراضي للحزم لبيئة تشغيل JavaScript، Node.js. على الرغم من أن اسمه الرسمي هو Node Package Manager، إلا أن مجتمع المطورين أطلق عليه أسماء فكاهية أخرى مثل “Ninja Pumpkin Mutants” أو “Nonprofit Pizza Makers”، ويمكنك استكشاف المزيد من هذه التسميات أو حتى المساهمة فيها عبر موقع npm-expansions.

يتكون npm بشكل أساسي من جزأين رئيسيين يعملان بتناغم:

  • أداة واجهة سطر الأوامر (CLI): وهي الأداة التي تستخدمها مباشرة من طرفية جهازك لنشر الحزم وتنزيلها.
  • مستودع الحزم عبر الإنترنت (npmjs.com): وهو بمثابة مكتبة ضخمة تستضيف ملايين حزم JavaScript الجاهزة للاستخدام.

لتوضيح الأمر بصورة بصرية، يمكننا تخيل موقع npmjs.com كمستودع مركزي عملاق لتلبية الطلبات. يستقبل هذا المستودع الحزم من “البائعين” (مؤلفي حزم npm) ويوزعها على “المشترين” (مستخدمي حزم npm). لتسهيل هذه العملية، يوظف مركز npmjs.com جيشًا من “حيوانات الومبات” المجتهدة (التي تمثل أداة npm CLI) والتي تعمل كمساعدين شخصيين لكل عميل.

إليك كيف يتم توصيل التبعيات لمطوري JavaScript:

رسم توضيحي لحيوان ومبات يوصل حزمة npm لمطور Node.js

وعملية نشر حزمة لمشاركتها مع زملائك في تطوير JavaScript ستكون على النحو التالي:

رسم توضيحي لحيوان ومبات ينشر حزمة npm في المستودع

دعنا الآن نستكشف كيف يساعد هذا “الجيش” من الومبات المطورين الذين يرغبون في استخدام حزم JavaScript في مشاريعهم، وكيف يدعمون مبدعي المصادر المفتوحة في إيصال مكتباتهم الرائعة إلى العالم.

ملف package.json: هوية مشروعك

يُعد ملف package.json بمثابة بطاقة هوية لكل مشروع JavaScript، سواء كان تطبيق Node.js أو تطبيقًا يعمل في المتصفح. هذا الملف النصي بتنسيق JSON هو المسؤول عن وصف المشروع وتحديد معلومات الحزمة الخاصة به. تخيل أن ملف package.json هو الملصق المطبوع على صناديق حزم npm التي يوزعها جيش الومبات لدينا.

يتم إنشاء ملف package.json تلقائيًا عند تشغيل الأمر npm init لتهيئة مشروع JavaScript أو Node.js جديد. يتطلب هذا الأمر من المطورين توفير بعض البيانات الوصفية الأساسية، والتي تشمل:

  • name: اسم مكتبة JavaScript أو المشروع الخاص بك. يجب أن يكون فريدًا عند النشر على npmjs.com.
  • version: رقم إصدار مشروعك. غالبًا ما يتم إهمال هذا الحقل في تطوير التطبيقات لأنه لا توجد حاجة واضحة لترقيم الإصدارات للمكتبات مفتوحة المصدر. ومع ذلك، يمكن أن يكون مفيدًا كمصدر لإصدار النشر أو التوزيع.
  • description: وصف موجز ومفيد للمشروع. يساعد هذا الوصف المستخدمين على فهم الغرض من الحزمة.
  • license: نوع الترخيص الذي يحكم استخدام مشروعك. هذا مهم للمشاريع مفتوحة المصدر.

npm scripts: أتمتة المهام في مشروعك

بالإضافة إلى البيانات الوصفية، يدعم ملف package.json خاصية بالغة الأهمية تُدعى scripts. تتيح لك هذه الخاصية تعريف أوامر سطر الأوامر التي يمكن تشغيلها ضمن سياق مشروعك المحلي. هذا يعني أنه يمكنك أتمتة مهام متكررة مثل بناء المشروع، تنسيق الكود، تشغيل الاختبارات، أو تحليل الكود البرمجي (linting).

على سبيل المثال، يمكن أن يبدو جزء scripts في مشروع npm على النحو التالي:

{
  "scripts": {
    "build": "tsc",
    "format": "prettier --write **/*.ts",
    "format-check": "prettier --check **/*.ts",
    "lint": "eslint src/**/*.ts",
    "pack": "ncc build",
    "test": "jest",
    "all": "npm run build && npm run format && npm run lint && npm run pack && npm test"
  }
}

الجميل في هذه الخاصية هو أن أدوات مثل eslint و prettier و ncc و jest لا تحتاج بالضرورة إلى أن تكون مثبتة بشكل عام على جهازك. بدلاً من ذلك، يتم تثبيتها محليًا لمشروعك داخل المجلد node_modules/.bin/. ومع التقديم الأخير لأداة npx، أصبح بإمكاننا تشغيل هذه الأوامر المحلية الخاصة بالمشروع وكأنها برامج مثبتة عالميًا، وذلك ببساطة عن طريق إضافة البادئة npx قبل الأمر (على سبيل المثال: npx prettier --write **/*.ts).

dependencies و devDependencies: التبعيات الأساسية والتطويرية

في أي مشروع برمجي، غالبًا ما نعتمد على مكتبات وحزم خارجية لتبسيط عملية التطوير. يقوم ملف package.json بتصنيف هذه التبعيات إلى قسمين رئيسيين: dependencies (التبعيات الأساسية) و devDependencies (تبعيات التطوير).

  • dependencies: تحتوي على الحزم الضرورية لتشغيل تطبيقك في بيئة الإنتاج. بدون هذه الحزم، لن يعمل تطبيقك بشكل صحيح.
  • devDependencies: تحتوي على الحزم المستخدمة فقط أثناء عملية التطوير والاختبار، مثل أدوات الاختبار (jest)، أدوات تحليل الكود (eslint)، أو أدوات التنسيق (prettier). هذه الحزم ليست ضرورية لتشغيل التطبيق في بيئة الإنتاج.

يتم تمثيل كلتا الخاصيتين ككائنات (key-value objects) حيث يكون المفتاح هو اسم مكتبة npm والقيمة هي إصدارها المنسق دلاليًا. إليك مثال من قالب TypeScript Action الخاص بـ GitHub:

{
  "dependencies": {
    "@actions/core": "^1.2.3",
    "@actions/github": "^2.1.1"
  },
  "devDependencies": {
    "@types/jest": "^25.1.4",
    "@types/node": "^13.9.0",
    "@typescript-eslint/parser": "^2.22.0",
    "@zeit/ncc": "^0.21.1",
    "eslint": "^6.8.0",
    "eslint-plugin-github": "^3.4.1",
    "eslint-plugin-jest": "^23.8.2",
    "jest": "^25.1.0",
    "jest-circus": "^25.1.0",
    "js-yaml": "^3.13.1",
    "prettier": "^1.19.1",
    "ts-jest": "^25.2.1",
    "typescript": "^3.8.3"
  }
}

يتم تثبيت هذه التبعيات باستخدام الأمر npm install مع علامات --save (لـ dependencies) و --save-dev (لـ devDependencies). سنتعمق أكثر في عملية تثبيت هذه الحزم في القسم التالي. في هذه الأثناء، من المهم فهم العلامات المحتملة التي تسبق أرقام الإصدارات الدلالية (بافتراض أنك على دراية بنموذج major.minor.patch لترقيم الإصدارات الدلالي semver):

  • ^: يشير إلى أحدث إصدار ثانوي (minor release). على سبيل المثال، قد يؤدي تحديد ^1.0.4 إلى تثبيت الإصدار 1.3.0 إذا كان هذا هو أحدث إصدار ثانوي ضمن السلسلة الرئيسية 1.
  • ~: يشير إلى أحدث إصدار تصحيحي (patch release). بنفس الطريقة التي يعمل بها ^ للإصدارات الثانوية، قد يؤدي تحديد ~1.0.4 إلى تثبيت الإصدار 1.0.7 إذا كان هذا هو أحدث إصدار تصحيحي ضمن السلسلة الثانوية 1.0.

سيتم توثيق جميع إصدارات الحزم الدقيقة هذه في ملف يتم إنشاؤه تلقائيًا يُسمى package-lock.json.

package-lock.json: ضمان استقرار بيئة المشروع

إذا كان ملف package.json بمثابة بطاقة وصف عامة لمشروعك، فإن ملف package-lock.json هو بمثابة قائمة مكونات دقيقة. يصف هذا الملف الإصدارات الدقيقة والفرعية لكل تبعية مستخدمة في مشروع JavaScript الخاص بك. على عكس package.json، ليس المقصود من package-lock.json أن يقرأه المطورون سطرًا بسطر (إلا إذا كنت تحاول يائسًا حل مشكلات “يعمل على جهازي”).

يتم إنشاء ملف package-lock.json عادةً بواسطة الأمر npm install. الأهم من ذلك، أن أداة npm CLI تقرأ هذا الملف لضمان إعادة إنتاج بيئات البناء للمشروع بشكل متطابق عبر الأجهزة المختلفة، خاصة عند استخدام الأمر npm ci. هذا يضمن أن كل مطور يعمل على المشروع، أو أي بيئة تكامل مستمر (CI)، يستخدم نفس الإصدارات الدقيقة من جميع التبعيات، مما يقلل من مشكلات التوافق.

إتقان npm كمستهلك للحزم

كما أشرنا سابقًا، مع وجود أكثر من 1.3 مليون حزمة منشورة مقابل 16 مليار تنزيل أسبوعي، يتضح أن الغالبية العظمى من مستخدمي npm هم مستهلكون للحزم. لذا، من الضروري معرفة كيفية استخدام هذه الأداة القوية بفعالية لتلبية احتياجات مشاريعك.

الأمر npm install: تثبيت الحزم بكفاءة

يُعد الأمر npm install الأكثر استخدامًا في تطوير تطبيقات JavaScript و Node.js اليوم. بشكل افتراضي، عند تشغيل npm install <اسم-الحزمة>، سيتم تثبيت أحدث إصدار من الحزمة مع علامة الإصدار ^.

عند تشغيل npm install بدون تحديد اسم حزمة ضمن سياق مشروع npm، سيقوم بتنزيل جميع الحزم المذكورة في ملف package.json إلى مجلد node_modules الخاص بالمشروع. سيقوم أيضًا بترقية إصدارات الحزم (وبالتالي إعادة إنشاء ملف package-lock.json) كلما أمكن ذلك بناءً على مطابقة الإصدارات ^ و ~.

إذا كنت ترغب في تثبيت حزمة في سياق عام لتتمكن من استخدامها في أي مكان على جهازك، يمكنك تحديد العلامة -g (اختصار لـ --global). هذا شائع لأدوات سطر الأوامر مثل live-server.

لقد جعل npm تثبيت حزم JavaScript أمرًا سهلاً للغاية، لدرجة أن هذا الأمر غالبًا ما يُستخدم بشكل غير صحيح، مما يؤدي إلى بعض النكات الشائعة بين المبرمجين مثل هذه:

صورة فكاهية حول حجم مجلد node_modules بعد تثبيت حزم npm

هنا يأتي دور العلامة --production! في القسم السابق، ناقشنا الفروقات بين dependencies و devDependencies، والتي تُستخدم لبيئات الإنتاج والتطوير/الاختبار على التوالي. تكمن أهمية علامة --production في أنها تحدد أي الحزم سيتم تثبيتها في مجلد node_modules. عند إرفاق هذه العلامة بالأمر npm install، سنقوم بتثبيت الحزم من قسم dependencies فقط، مما يقلل بشكل كبير من حجم مجلد node_modules إلى ما هو ضروري تمامًا لتشغيل تطبيقاتنا. تمامًا كما لا يحضر الكشافة عصارات الليمون إلى كشك عصير الليمون، لا ينبغي لنا أن نحضر devDependencies إلى بيئة الإنتاج!

npm ci: التثبيت النظيف والمتسق

إذا كان الأمر npm install --production مثاليًا لبيئة الإنتاج، فهل هناك أمر مثالي لبيئات التطوير والاختبار المحلية؟ الإجابة هي نعم، وهو الأمر npm ci (اختصار لـ Clean Install أو Continuous Integration).

بينما يقوم npm install بإنشاء ملف package-lock.json إذا لم يكن موجودًا، فإن npm ci يعتمد بشكل كامل على هذا الملف. يقوم npm ci بتنزيل الإصدارات الدقيقة لكل حزمة يعتمد عليها المشروع، كما هو محدد في package-lock.json. هذه الطريقة تضمن أن سياق مشروعك يظل متطابقًا تمامًا عبر الأجهزة المختلفة، سواء كانت أجهزة الكمبيوتر المحمولة المستخدمة للتطوير أو بيئات البناء للتكامل المستمر (CI) مثل GitHub Actions. هذا يقلل بشكل كبير من مشكلات “يعمل على جهازي” ويضمن بيئة تطوير متسقة وموثوقة.

npm audit: فحص أمان التبعيات

مع العدد الهائل من الحزم التي تم نشرها والتي يمكن تثبيتها بسهولة، أصبحت حزم npm عرضة لمؤلفين سيئين ذوي نوايا خبيثة. إدراكًا لهذه المشكلة في المنظومة، ابتكرت منظمة npm.js فكرة npm audit. تحتفظ المنظمة بقائمة من الثغرات الأمنية المعروفة التي يمكن للمطورين فحص تبعياتهم مقابلها باستخدام الأمر npm audit.

يوفر الأمر npm audit للمطورين معلومات مفصلة حول الثغرات الأمنية المكتشفة، وما إذا كانت هناك إصدارات تحتوي على إصلاحات يمكن الترقية إليها. على سبيل المثال:

مثال على نتيجة فحص npm audit تظهر الثغرات الأمنية

إذا كانت الإصلاحات متاحة في ترقيات الإصدارات غير المتعارضة التالية، يمكن استخدام الأمر npm audit fix لترقية إصدارات التبعيات المتأثرة تلقائيًا، مما يعزز أمان مشروعك بشكل كبير.

إتقان npm كمؤلف للحزم

بعد أن استعرضنا كيفية استخدام أداة npm CLI كمستهلك للحزم، ماذا عن استخدامها بفعالية كمؤلف للحزم (وربما تصبح ساحرًا في عالم المصادر المفتوحة لـ JavaScript

npm publish: مشاركة إبداعاتك مع العالم

إرسال حزمة إلى مركز تلبية طلبات npmjs.com الخاص بنا أمر سهل للغاية؛ كل ما عليك فعله هو تشغيل الأمر npm publish. الجزء الصعب، والذي لا يقتصر على مؤلفي حزم npm فقط، هو تحديد إصدار الحزمة. القاعدة الذهبية وفقًا لموقع semver.org هي:

  • إصدار رئيسي (MAJOR): عندما تُجري تغييرات غير متوافقة مع الإصدارات السابقة في واجهة برمجة التطبيقات (API).
  • إصدار ثانوي (MINOR): عندما تُضيف وظائف جديدة بطريقة متوافقة مع الإصدارات السابقة.
  • إصدار تصحيحي (PATCH): عندما تُجري إصلاحات للأخطاء متوافقة مع الإصدارات السابقة.

من الأهمية بمكان اتباع هذه القواعد عند نشر حزمك لضمان عدم إفساد كود أي شخص آخر، نظرًا لأن مطابقة الإصدار الافتراضية في npm هي ^ (أي الإصدار الثانوي التالي).

الخلاصة التقنية

يُعد npm أكثر من مجرد مدير حزم؛ إنه العمود الفقري لمنظومة Node.js و JavaScript بأكملها. من خلال فهم آلياته الأساسية، بدءًا من ملف package.json وهياكل التبعيات وصولًا إلى أوامر التثبيت والنشر والفحص الأمني، يمكن للمطورين تسريع عملية تطويرهم بشكل كبير، والحفاظ على استقرار مشاريعهم، والمساهمة بفعالية في مجتمع المصادر المفتوحة. إن إتقان npm ليس مجرد مهارة تقنية، بل هو مفتاح لفتح إمكانيات لا حصر لها في عالم تطوير الويب الحديث، مما يجعله أداة لا غنى عنها لكل مطور طموح.

وبهذا، نكون قد استعرضنا كل ما تحتاج معرفته للبدء في استخدام npm بفعالية والتحكم في “جيش الومبات” الخاص بك!

صورة لحيوانات الومبات اللطيفة، رمز لمدير حزم npm

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *