الطريق إلى تبعيات جافا سكريبت الجحيم

يبدأ كل مشروع جافا سكريبت بنوايا حسنة ، أي أن منشئي المحتوى يعدون أنفسهم بعدم استخدام الكثير من حزم NPM أثناء تطويره. ولكن حتى لو بذل المطورون جهودًا كبيرة للوفاء بهذا الوعد ، فإن حزم NPM تخترق مشاريعهم تدريجيًا. package.jsonيزداد حجم الملف بمرور الوقت. ومع package-lock.jsonتثبيت التبعيات ، يحدث رعب حقيقي ، يتم التعبير عنه في الإضافات وحذف الحزم ، ملحوظة بشكل خاص مع العلاقات العامة التالية ... "كل شيء على ما يرام" ، يقول قائد الفريق. أومأ باقي الفريق برأس الموافقة. ماذا تفعل؟ نتمتع جميعًا بحقيقة أن نظام جافا سكريبت الحيوي على قيد الحياة وبصحة جيدة. لسنا بحاجة إلى إعادة اختراع العجلة في كل مرة ومحاولة حل المشكلات التي تم حلها بالفعل من قبل مجتمع المصادر المفتوحة.





لنفترض أنك ستنشئ مدونة وتريد استخدام Gatsby.js. حاول إضافة مولد الموقع هذا بناءً على مشروعك. الآن ، مبروك. يحتوي مشروعك للتو على 19000 تبعية إضافية. هذا امر طبيعي؟ ما مدى تعقيد شجرة تبعية JavaScript؟ كيف تتحول شجرة التبعية إلى جحيم؟ دعونا نكتشف ذلك.

ما هي حزمة JavaScript؟


يخزن NPM (Node Package Manager ، Node Package Manager) أكبر سجل حزم في العالم. هذه حزم JavaScript. NPM أكثر من RubyGems و PyPi و Maven مجتمعين. يمكن إجراء هذا الاستنتاج على أساس تحليل بيانات مشروع تعداد الوحدات ، والذي يراقب عدد الحزم في السجلات الشائعة.


بيانات عن عدد الحزم في السجلات الشائعة

قد تعتقد أن كميات كبيرة جدًا من التعليمات البرمجية ممثلة في هذا الرسم البياني. على ما هو عليه. من أجل تحويل مشروع إلى حزمة NPM ، يجب أن تحتوي هذه الحزمة على ملفpackage.json. يمكن إرسال هذه الحزمة إلى سجل الآلية الوقائية الوطنية.

ما هو package.json؟


فيما يلي المهام التي يحلها package.json:

  • يسرد الحزم التي يعتمد عليها مشروعك (هذه قائمة بتبعيات المشروع).
  • في ذلك ، باستخدام قواعد الإصدار الدلالي ، يتم تعيين إصدارات حزم التبعية التي يمكن أن يستخدمها مشروعك.
  • يسمح لك بإعادة إنتاج البيئة اللازمة لعمل الحزمة ، ونتيجة لذلك ، يبسط نقل المشروع إلى مطورين آخرين.

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

ولعل حقيقة أن تبعيات المشروع موضحة في هذا الملف تبدو مزعجة إلى حد ما. تخيل أن هناك حزمة تعتمد على حزمة أخرى ، وأن هذه الحزمة الأخرى تعتمد على حزمة أخرى. يمكن أن تكون سلسلة التبعيات طويلة بشكل تعسفي. لهذا السبب ، يعني تثبيت الحزمة الوحيدة ، Gatsby.js ، تزويد المشروع بـ 19000 تبعية إضافية.

أنواع التبعية في package.json


من أجل فهم أفضل لكيفية نمو قوائم تبعيات المشروع بمرور الوقت ، لنتحدث عن الأنواع المختلفة من التبعيات التي قد يمتلكها المشروع. على وجه التحديد ، package.jsonيمكن العثور على الأقسام التالية التي تصف التبعيات المختلفة:

  • dependencies - هذه هي تبعيات عادية ، يتم استخدام وظائفها في المشروع ، ويتم الوصول إليها من التعليمات البرمجية الخاصة به.
  • devDependencies- هذه هي تبعيات التنمية. على سبيل المثال ، تستخدم مكتبة أجمل لتنسيق التعليمات البرمجية.
  • peerDependencies - في حالة كتابة التبعيات في هذا القسم ، يقوم مطور الحزمة بالتالي بإبلاغ الشخص الذي سيقوم بتثبيته أنه سيحتاج إلى إصدار محدد من الحزمة المحددة في هذا القسم.
  • optionalDependencies - يسردون التبعيات الاختيارية ، مثل عدم القدرة على التثبيت والتي لن تنتهك عملية تثبيت الحزمة.
  • bundledDependencies — , . , NPM, , .

package-lock.json


نعلم جميعًا أن الملف package-lock.json، أثناء العمل على المشروع ، يخضع للتغييرات باستمرار. يتم إزالة شيء منه ، ويضاف إليه شيء. هذا ملحوظ بشكل خاص عند عرض العلاقات العامة التي تحتوي على نسخة محدثة من هذا الملف. كثيرا ما نأخذها كأمر مسلم به. يتم package-lock.jsonإنشاء ملف تلقائيًا في كل مرة يتغير فيها ملف package.jsonأو مجلد node_modules. هذا يسمح لك بالحفاظ على محتويات شجرة التبعية كما كانت بالضبط عند تثبيت تبعيات المشروع. هذا يسمح ، عند تثبيت المشروع ، بإعادة إنتاج شجرة التبعية. هذا يحل مشكلة وجود إصدارات مختلفة من نفس الحزمة من مطورين مختلفين.

فكر في مشروع تتضمن تبعياته التفاعل. الإدخال المقابل متاح في package.json. إذا نظرت إلى الملفpackage-lock.json من هذا المشروع ، ثم يمكنك رؤية شيء مثل ما يلي:

    "react": {
      "version": "16.13.0",
      "resolved": "https://registry.npmjs.org/react/-/react-16.13.0.tgz",
      "integrity": "sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ==",
      "requires": {
        "loose-envify": "^1.1.0",
        "object-assign": "^4.1.1",
        "prop-types": "^15.6.2"
      }
    }

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

فهم تبعيات Gatsby.js


كيف ، بعد إنشاء تبعية واحدة فقط ، نضيف ما يصل إلى 19000 تبعية للمشروع؟ كل شيء عن تبعيات التبعية. لهذا السبب لدينا ما لدينا:

$ npm install --save gatsby

...

+ gatsby@2.19.28
added 1 package from 1 contributor, removed 9 packages, updated 10 packages and audited 19001 packages in 40.382s

إذا نظرت إلى package.jsonهناك ، يمكنك العثور على تبعية واحدة فقط. ولكن إذا نظرت إليها package-lock.json، اتضح أنه أمامنا وحش يبلغ وزنه 14 كيلوبايت تقريبًا. يمكن العثور على إجابة أكثر تفصيلاً حول كل أسطر التعليمات البرمجية التي تقع في الوسط package-lock.json، في الملف package.jsonفي مستودع Gatsby.js . هناك الكثير من التبعيات المباشرة ، وبالتحديد وفقًا لحسابات npm ، 132. إذا كان لكل من هذه التبعيات تبعية واحدة على الأقل ، فإن العدد الإجمالي لاعتمادات المشروع سيتضاعف - وسيكون به 264 تبعية. بالطبع ، ليس الأمر كذلك في العالم الحقيقي. كل تبعية مباشرة للمشروع لها أكثر من تبعية متأصلة. ونتيجة لذلك ، فإن قائمة تبعيات المشروع طويلة جدًا.

على سبيل المثال ، سنهتم بعدد مرات استخدام مكتبة Lodash كتبعية لحزم أخرى :

$ npm ls lodash
example-js-package@1.0.0
└─┬ gatsby@2.19.28
  ├─┬ @babel/core@7.8.6
  │ ├─┬ @babel/generator@7.8.6
  │ │ └── lodash@4.17.15  deduped
  │ ├─┬ @babel/types@7.8.6
  │ │ └── lodash@4.17.15  deduped
  │ └── lodash@4.17.15  deduped
  ├─┬ @babel/traverse@7.8.6
  │ └── lodash@4.17.15  deduped
  ├─┬ @typescript-eslint/parser@2.22.0
  │ └─┬ @typescript-eslint/typescript-estree@2.22.0
  │   └── lodash@4.17.15  deduped
  ├─┬ babel-preset-gatsby@0.2.29
  │ └─┬ @babel/preset-env@7.8.6
  │   ├─┬ @babel/plugin-transform-block-scoping@7.8.3
  │   │ └── lodash@4.17.15  deduped
  │   ├─┬ @babel/plugin-transform-classes@7.8.6
  │   │ └─┬ @babel/helper-define-map@7.8.3
  │   │   └── lodash@4.17.15  deduped
  │   ├─┬ @babel/plugin-transform-modules-amd@7.8.3
  │   │ └─┬ @babel/helper-module-transforms@7.8.6
  │   │   └── lodash@4.17.15  deduped
  │   └─┬ @babel/plugin-transform-sticky-regex@7.8.3
  │     └─┬ @babel/helper-regex@7.8.3
  │       └── lodash@4.17.15  deduped
  ...

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

$ du -sh node_modules
200M    node_modules

200 ميغا بايت ليست سيئة للغاية. لقد رأيت كيف يصل حجم هذا المجلد بسهولة إلى 700 ميغابايت. إذا كنت مهتمًا بمعرفة الوحدات التي تشغل أكبر مساحة ، فيمكنك تشغيل الأمر التالي:

$ du -sh ./node_modules/* | sort -nr | grep '\dM.*'
 17M    ./node_modules/rxjs
8.4M    ./node_modules/@types
7.4M    ./node_modules/core-js
6.8M    ./node_modules/@babel
5.4M    ./node_modules/gatsby
5.2M    ./node_modules/eslint
4.8M    ./node_modules/lodash
3.6M    ./node_modules/graphql-compose
3.6M    ./node_modules/@typescript-eslint
3.5M    ./node_modules/webpack
3.4M    ./node_modules/moment
3.3M    ./node_modules/webpack-dev-server
3.2M    ./node_modules/caniuse-lite
3.1M    ./node_modules/graphql
...

نعم ، rxjs هي حزمة خبيثة.

فيما يلي أمر بسيط يساعد على تقليل حجم المجلد node_modulesوتبسيط بنيته:

$ npm dedup
moved 1 package and audited 18701 packages in 4.622s

51 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

أثناء إلغاء البيانات المكررة ، يحاول npm تبسيط هيكل شجرة التبعية من خلال إيجاد التبعيات المستخدمة من قبل التبعيات الأخرى ونقلها بحيث يمكن مشاركتها. هذا ينطبق على مثال لوداش. lodash @4.17.15ونتيجة لذلك ، يتم استخدام العديد من الحزم لضمان تشغيلها ، ويكفي تثبيت هذا الإصدار من المكتبة مرة واحدة فقط. بالطبع ، هذا هو الوضع الذي ندخله منذ البداية ، فقط من خلال إنشاء التبعيات. إذا كنت في مرحلة العمل على مشروع package.jsonتضيف تبعيات جديدة ، فمن المستحسن أحيانًا تذكر الفريق npm dedup. إذا كنت تستخدم مدير حزمة الغزل ، فهناك أمر مشابه يشبه الغزل. ولكن ، في الواقع ، ليست هناك حاجة لذلك ، حيث يتم تنفيذ تحسين التبعية تلقائيًا عند تنفيذ الأمر yarn install.

تصور التبعية


هل أنت مهتم بتمثيل رسومي لتبعيات مشروعك؟ إذا كان الأمر كذلك ، يمكنك إنشاء عرض تقديمي باستخدام أدوات خاصة. دعونا نفكر في بعض منها.

فيما يلي نتيجة لتصور التبعية تم الحصول عليها باستخدام npm.anvaka.com/ .


تصور التبعية باستخدام npm.anvaka.com.

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

هنا تصوّر تم باستخدام npm.broofa.com .


جزء من تصور التبعية مصنوع باستخدام npm.broofa.com

هذا يشبه المخطط الانسيابي. إنها بالنسبة لـ Gatsby.js ، تبين أنها معقدة للغاية. يمكنك إلقاء نظرة عليه هنا . عناصر الدائرة يمكن أن تكون ملونة بناءا على تقديرات من npms.io . يمكنك تحميل ملفك الخاص إلى الموقعpackage.json. تتيح لك

أداة Package Phobia معرفة مقدار المساحة التي تحتاجها قبل تثبيت الحزمة.


معلومات الحزمة المستلمة باستخدام Package Phobia

هنا يمكنك معرفة حجم الحزمة المنشورة ، ومقدار مساحة القرص التي ستستغرقها بعد التثبيت.

خلاصة القول: مع القوة العظيمة تأتي مسؤولية كبيرة


في النهاية ، أود أن أقول إن JavaScript و NPM أدوات رائعة. الشيء الجيد هو أن المطورين الحديثين لديهم الفرصة لاستخدام مجموعة ضخمة من التبعيات. npm installمن السهل جدًا تشغيل الأمر من أجل إنقاذ نفسك من كتابة بضعة أسطر من التعليمات البرمجية بحيث ننسى أحيانًا العواقب.

الآن بعد أن قرأت حتى هذه النقطة ، يجب أن يكون لديك فهم أكثر اكتمالًا لميزات بنية شجرة تبعية مشروع npm. إذا قمت بإضافة مكتبة إلى المشروع كبيرة جدًا ، أو إذا قمت باستكشاف تبعيات مشروعك ، فيمكنك دائمًا الاستفادة مما ناقشناه هنا وتحليل التبعيات.

القراء الأعزاء! هل تريد استخدام أقل عدد ممكن من التبعيات في مشاريع npm الخاصة بك؟


All Articles