المشاريع Node.js التي من الأفضل عدم استخدام ملفات التأمين

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



أهم شيء باختصار


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

ما هو ملف القفل؟


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

إليك ما قد تبدو عليه package-lock.json .

 { "name": "lockfile-demo", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": {  "ansi-styles": {    "version": "3.2.1",    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",    "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",    "requires": {      "color-convert": "^1.9.0"    }  },  "chalk": {    "version": "2.4.2",    "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",    "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",    "requires": {      "ansi-styles": "^3.2.1",      "escape-string-regexp": "^1.0.5",      "supports-color": "^5.3.0"    }  } } } 

هنا مثال على ملف yarn.lock . لم يتم تصميمه مثل package-lock.json ، ولكنه يحتوي على بيانات مماثلة.

 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies:       color-convert "^1.9.0" chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies:       ansi-styles "^3.2.1"       escape-string-regexp "^1.0.5"       supports-color "^5.3.0" 

يحتوي كلا الملفين على بعض معلومات التبعية الحرجة:

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

إذا كانت جميع التبعيات مدرجة في ملف القفل ، فلماذا إذن يضيفون معلومات عنها إلى package.json ؟ لماذا هناك حاجة إلى ملفين؟

مقارنة بين package.json وقفل الملفات


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

افترض أن الأمر npm install قد تم تشغيله لتثبيت تبعيات مشروع معين. أثناء عملية التثبيت ، التقطت npm الحزم المناسبة. إذا قمت بتشغيل هذا الأمر مرة أخرى ، بعد فترة ، وإذا تم إصدار إصدارات جديدة من التبعيات خلال هذا الوقت ، فقد يحدث أن يتم تحميل إصدارات أخرى من الحزم المستخدمة في المشروع في المرة الثانية. على سبيل المثال ، إذا قمت بتثبيت تبعية ، مثل twilio ، باستخدام الأمر npm install twilio ، فقد يظهر الإدخال التالي في قسم dependencies من ملف package.json :

 { "dependencies": {    "twilio": "^3.30.3" } } 

إذا نظرت إلى وثائق الإصدار الدلالي npm ، يمكنك أن ترى أن علامة ^ تشير إلى أن أي إصدار من الحزمة مناسب ، وعدده أكبر من أو يساوي 3.30.3 وأقل من 4.0.0. نتيجة لذلك ، إذا لم يكن هناك ملف قفل في المشروع وتم إصدار إصدار جديد من الحزمة ، فإن npm install أو yarn install سوف يقوم تلقائيًا بتثبيت هذا الإصدار الجديد من الحزمة. لن يتم تحديث المعلومات الموجودة في package.json . عند استخدام ملفات القفل ، يبدو كل شيء مختلفًا.

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

 npm ci #   ,    package-lock.json yarn install --frozen-lock-file #  ,    yarn.lock,     

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

لماذا لا تفعل الشيء نفسه عند نشر المكتبات أو غيرها من أدوات البرمجيات في سجل npm؟ قبل الإجابة على هذا السؤال ، نحتاج إلى التحدث عن كيفية عمل عملية نشر الحزم.

حزمة عملية النشر


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

بعد ذلك ، يأخذ npm جميع الملفات المناسبة npm pack في ملف tarball باستخدام الأمر npm pack . إذا كنت تريد إلقاء نظرة على ما يتم npm pack --dry-run بالضبط في مثل هذا الملف ، يمكنك تشغيل الأمر npm pack --dry-run في مجلد المشروع وإلقاء نظرة على قائمة المواد في وحدة التحكم.


حزمة Npm - إخراج الأمر الجاف

ثم يتم تحميل ملف tarball الناتج إلى سجل npm. عند تشغيل الأمر npm pack --dry-run يمكنك الانتباه إلى حقيقة أنه إذا كان هناك ملف package-lock.json في المشروع ، فلن يتم تضمينه في ملف tarball. هذا يرجع إلى حقيقة أن هذا الملف ، وفقًا لقواعد npm ، يتم تجاهله دائمًا.

والنتيجة هي أنه إذا قام شخص ما بتثبيت حزمة شخص آخر ، فلن يتم package-lock.json ملف package-lock.json . ما في هذا الملف أن مطور الحزمة لن يؤخذ في الاعتبار عند تثبيت الحزمة من قبل شخص آخر.

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

رفض قفل الملفات واستخدام التكنولوجيا shrinkwrap


تحتاج أولاً إلى منع إدراج ملفات القفل في مستودع المشروع. عند استخدام git ، يلزمك تضمين ما يلي في ملف .gitignore الخاص .gitignore :

 yarn.lock package-lock.json 

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

يمكنك تعطيل الإنشاء التلقائي لملف package-lock.json عن طريق .npmrc ملف .npmrc بالمحتويات التالية إلى مجلد المشروع:

 package-lock=false 

عند العمل مع الغزل ، يمكنك استخدام أمر yarn install --no-lockfile ، والذي يسمح لك بتعطيل قراءة ملف yarn.lock .

ومع ذلك ، لا يعني حقيقة أننا تخلصنا من ملف package-lock.json أننا لا نستطيع التقاط معلومات حول التبعيات والتبعيات المتداخلة. يوجد ملف آخر يسمى npm-shrinkwrap.json .

بشكل عام ، هذا هو نفس ملف package-lock.json ، يتم إنشاؤه بواسطة npm shrinkwrap . يحصل هذا الملف على سجل npm عند نشر الحزمة.

من أجل أتمتة هذه العملية ، يمكن إضافة npm shrinkwrap إلى قسم وصف البرنامج النصي لملف package.json كبرنامج نصي prepack. يمكنك تحقيق نفس التأثير باستخدام ربط ربط git. نتيجة لذلك ، يمكنك التأكد من أنه في بيئة التطوير الخاصة بك ، في نظام CI الخاص بك ، وأن مستخدمي مشروعك يستخدمون نفس التبعيات.

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

العثور على حزمة ومعلومات التبعية


لسوء الحظ ، مع وجود مجموعة كبيرة من المعلومات حول إدارة التبعية في وثائق npm ، يصعب أحيانًا التنقل في هذه المعلومات. إذا كنت تريد أن تعرف بالضبط ما تم تثبيته أثناء تثبيت التبعيات أو تم حزمه قبل إرسال الحزمة إلى npm ، يمكنك ، باستخدام أوامر مختلفة ، استخدام --dry-run . يؤدي استخدام هذه العلامة إلى حقيقة أن الفريق لا يؤثر على النظام. على سبيل المثال ، لا npm install --dry-run الأمر npm install --dry-run فعلياً التبعيات ، ولا npm publish --dry-run الأمر npm publish --dry-run عملية نشر الحزمة.

فيما يلي بعض الأوامر المشابهة:

 npm ci --dry-run #  ,   package-lock.json   npm-shrinkwrap.json npm pack --dry-run #     ,       npm install <dep> --verbose --dry-run #            

النتائج


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

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

أعزائي القراء! هل تستخدم ملف npm-shrinkwrap.json في مشاريعك؟

Source: https://habr.com/ru/post/ar453582/


All Articles