Yarn: مساحات العمل: قفل الملف لكل مساحة عمل

تم إنشاؤها على ٢٨ فبراير ٢٠١٨  ·  54تعليقات  ·  مصدر: yarnpkg/yarn

هل تريد طلب ميزة أو الإبلاغ عن خطأ ؟
خاصية

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

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

مثال:
إذا كان لدي monorepo مع مساحتي عمل: workspace-a و workspace-b . يستخدم workspace-a بعض الوحدات المصدرة من workspace-b . إذا كنت أرغب في حزم workspace-a في صورة عامل إرساء (أو أي طريقة أخرى لتعبئة مساحة العمل هذه بمفردها ، بدون monorepo بالكامل) ، فليس لدي yarn.lock لذلك. هذا يعني أنه عندما أقوم بنقل ملفات workspace-a إلى بيئة مختلفة بخلاف monorepo ، سأفقد ملف yarn.lock وعند تثبيت التبعيات ، سأفقد كل مزايا ملف القفل (مع العلم أنني أقوم بتثبيت نفس التبعيات المستخدمة في التطوير).

أنا مندهش تمامًا من أنني لم أجد مشكلة في هذا الشأن. هل أنا الوحيد الذي يريد العمل مع monorepos بهذه الطريقة؟ ربما أفتقد شيئا؟ الحل الحالي الخاص بي يستخدم lerna بدون رفع على الإطلاق ، لذلك سيكون لدي ملف قفل لكل حزمة.
لا يبدو أن ميزة nohoist تم إصدارها مؤخرًا تساعد أيضًا (على الرغم من أنني كنت آمل) ، لأنها لا تخلق yarn.lock مختلفًا لكل مساحة عمل.
هذه المسألة مرتبطة إلى حد ما بهذا التعليق على قضية أخرى. يعتقد أنه قد يستحق قضية خاصة به.

يرجى ذكر node.js والغزل وإصدار نظام التشغيل.
العقدة 8.9.3 ، الغزل 1.5.1 ، OSX 10.13.3

cat-feature triaged

التعليق الأكثر فائدة

لذلك ، بالنسبة لنا ، لا نريد تجميع المونوريبو بالكامل في حاوية عامل الإرساء الناتجة. نحن نستخدم عامل ميناء في الإنتاج ويجب أن تكون تلك الصور خفيفة قدر الإمكان. يعد الريبو الأحادي الخاص بنا كبيرًا جدًا ويحتوي على العديد من الخدمات الصغيرة التي تشترك في التعليمات البرمجية بينها باستخدام حزم المكتبة (وبعض المكتبات ذات صلة ببعض الخدمات المصغرة ، ولكن ليس كلها). لذلك عندما نقوم بحزم خدمة مصغرة ، نريد أن تحتوي الصورة على ملفات تلك الخدمة المصغرة وأي تبعيات أخرى باعتبارها تبعيات مناسبة - يتم تنزيلها من السجل الخاص بنا ، ومُصممة لقوس صورة عامل الإرساء.

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

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

آمل أن يكون قد ساعد في توضيح حالة الاستخدام .. 🍻

ال 54 كومينتر

بناء على مدونة الغزل :

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

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

connectdotz قد لا تكون هناك حاجة لمكتبة أو حزمة منشورة ولكن لبناء حاوية عامل

بالتأكيد ... لكن ألا تحتوي حاوية عامل البناء التطوير على الريبو بالكامل وبالتالي قفل الغزل على أي حال؟ أستطيع أن أرى أننا نستخدم حاويات docker لاختبار مشروع monorepo الخاص بنا لأنظمة تشغيل أو منصات مختلفة ، وفي هذه الحالة نقوم فقط بنشر الريبو بالكامل و yarn.lock الخاص به. هل يمكن أن تعطيني مثالًا لحالة الاستخدام التي تحتاجها لنشر الحزم الفردية من مشروع monorepo في حاويات الرصيف أثناء دورة التطوير ، حتى أتمكن من الحصول على فهم أكثر واقعية ...

لذلك ، بالنسبة لنا ، لا نريد تجميع المونوريبو بالكامل في حاوية عامل الإرساء الناتجة. نحن نستخدم عامل ميناء في الإنتاج ويجب أن تكون تلك الصور خفيفة قدر الإمكان. يعد الريبو الأحادي الخاص بنا كبيرًا جدًا ويحتوي على العديد من الخدمات الصغيرة التي تشترك في التعليمات البرمجية بينها باستخدام حزم المكتبة (وبعض المكتبات ذات صلة ببعض الخدمات المصغرة ، ولكن ليس كلها). لذلك عندما نقوم بحزم خدمة مصغرة ، نريد أن تحتوي الصورة على ملفات تلك الخدمة المصغرة وأي تبعيات أخرى باعتبارها تبعيات مناسبة - يتم تنزيلها من السجل الخاص بنا ، ومُصممة لقوس صورة عامل الإرساء.

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

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

آمل أن يكون قد ساعد في توضيح حالة الاستخدام .. 🍻

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

بينما يمكنني رؤية استخدام ملفات القفل الفردية ، فهي ليست ضرورية. إذا قمت بتشغيل docker من جذر الريبو باستخدام علامة -f تشير إلى الملفات الفردية ، فسيكون لديك الريبو بالكامل كسياق ويمكنك نسخه في package.json و yarn.lock من الجذر.

تحتاج فقط إلى package.json للحزم التي ستنشئها في الصورة ، وسوف يقوم الغزل بتثبيت الحزم فقط لتلك الحزمة.

تحرير: مع ذلك قال. يتسبب في عدم استخدام ذاكرة التخزين المؤقت لـ docker لتغييرات الحزمة في أي حزمة على الرغم من عدم تضمينها في الإنشاء

4206 مرتبط / مكرر ، وحالة الاستخدام الموضحة هناك بالضبط المشكلة التي نواجهها:

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

لدي مشاكل مماثلة مع مساحات العمل. مشروعي هو web-app والذي يعتمد على العديد من الحزم المحلية:

web-app/
|--node_modules/
|--packages/
|  |--controls/
|  |  |--src/
|  |  |--package.json
|  |--utils/
|     |--src/
|     |--package.json
|--src/
|--package.json
|--yarn.lock

حزم مساحة العمل controls و utils غير منشورة وتستخدم بواسطة المسارات. المشكلة هي أنني بحاجة إلى إصدار حزمة controls ( yarn pack ) ولن أقوم ببنائها / اختبارها بمفردها. هذا يعني أنني أريد أن أفعل yarn install داخل web-app/packages/constols/ . مع مساحات العمل ، سيتم استخدام ملف المستوى الأعلى web-app/yarn.lock مع المستوى الأعلى web-app/node-modules/ . لذلك ، يقوم بتثبيت جميع الحزم بدلاً من مجموعة فرعية ، المحددة في web-app/packages/controls/package.json . لكني أحتاج إلى التحقق من أن الحزمة الخاصة بي تحتوي على جميع التبعيات المطلوبة في package.json ولا تعمل عن طريق الحظ لملء الأجزاء المفقودة من مساحات العمل الأخرى.

يوجد حلان محتملان:

  1. إذا لم يكن الجذر ، فاستخدم الجذر yarn.lock ، لكن قم بتثبيت الحزم المحددة فقط في package.json المحلي.
  2. لا تبحث عن تكوينات المستوى الأعلى ، ولكن .yarnrc/.npmrc .

أيضا تكافح مع هذا. لدينا مشروع Angular CLI جنبًا إلى جنب مع API الخاص بنا ، لذا فهم في نفس المستودع ومحاولة دفع الواجهة الأمامية إلى Heroku.

نحن نستخدم حزمة buildpack تخبر Heroku بالقفز إلى مستودع الواجهة الأمامية أولاً: https://github.com/lstoll/heroku-buildpack-monorepo

المشكلة هي أنه لا يوجد yarn.lock داخل حزمة nohoist لذلك يتم تثبيت Heroku فقط باستخدام npm وينتهي بنا الأمر مع جميع الحزم الجديدة بدلاً من الحزم المقفلة

يمكنك فقط استخدام ملف yarn.lock العام مع الحزم الفردية. لقد اقتربت مؤخرًا من ملف Docker الخاص بي مثل هذا:

WORKDIR /app
ENV NODE_ENV=production

ADD yarn.lock /app/
ADD package.json /app/

# Only copy the packages that I need
ADD packages/my-first-package /app/packages/my-first-package
ADD packages/my-second-package /app/packages/my-second-package

RUN cd /app && yarn install --frozen-lockfile

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

لدي عملية بناء حيث أود أولاً إنشاء عنصر إصدار من حزمة واحدة ثم عدم تثبيت أي من تبعياتها. هذا سهل إلى حد ما مع بناء Docker

  1. أضف فقط yarn.lock و package.json وحزمة واجهة المستخدم إلى عامل الإرساء
  2. تشغيل yarn install --frozen-lockfile
  3. قم بتشغيل عملية البناء
  4. ابدأ مرحلة جديدة وأضف yarn.lock و package.json وحزم وقت التشغيل / مجلدات مساحة العمل الضرورية
  5. قم بعمل COPY --from=<stage> للقطعة الأثرية المبنية
  6. قم بتشغيل yarn install --frozen-lockfile واكشف الأمر RUN .

وستنتهي بحاوية صغيرة تحتوي فقط على التبعيات المحددة في ملف yarn.lock والمطلوبة في الإنتاج.

@ johannes-scharlach
انتهى بي الأمر باستخدام طريقة متطابقة تقريبًا لما تصفه. بناء متعدد المراحل هو نصيحة جيدة :).

connectdotz أعتقد أنه من ناحيتي ، يمكن إغلاق هذه المشكلة ويمكننا مواصلة العمل على المشكلة رقم 4521. نظرًا لأن ملف yarn.lock الرئيسي يمكن أن يعمل مع مجموعة فرعية من الحزم ، يبدو أن قفل yarn.lock لكل مساحة عمل ليس ضروريًا (على الرغم من أنني ما زلت أعتقد أن هذا يمكن أن يكون سير عمل أفضل لتطوير 😉). لكن المشكلة في # 4521 لا تزال مهمة ، لأنه في الحل الذي وصلنا إليه هنا ، نحتاج إلى ذكر كل مساحة عمل تبعية في Dockerfile على الرغم من أن الغزل يجب أن يعرف الترابط وكيف "البائع" مساحة عمل معينة.

قضيت اليومين الماضيين في محاولة تحويل monorepo إلى Lerna أولاً ثم مساحات عمل Yarn. عملت الغزل بشكل عام بشكل أكثر موثوقية وهي قريبة حقًا مما نحتاج إليه ، خاصة مع التقديم الأخير لـ yarn workspaces run <script> وأشياء لطيفة أخرى مثل wsrun .

ومع ذلك ، فإن المنفرد yarn.lock يمثل نقطة ضعف:

  • لست متأكدًا من كيفية ترحيل ملفات القفل الحالية بشكل صحيح إلى ملف واحد ، راجع https://github.com/yarnpkg/yarn/issues/6563. لدينا عشرات الآلاف من السطور هناك وإضافة الحزم الحالية حيث قدمت مساحات العمل العديد من مشكلات الإصدار الدقيقة.
  • تثبيت التبعيات في حزمة معينة فقط ("de-hoisting" / "vendoring") بنية Dockerized غير مدعومة جيدًا ، انظر أعلاه (https://github.com/yarnpkg/yarn/issues/5428#issuecomment-403722271) أو https: //github.com/yarnpkg/yarn/issues/4521.

ما رأيك في أن تكون مساحات عمل Yarn مجرد نواة صغيرة - إعلان عن الحزم دون أي وظائف محددة. على سبيل المثال:

  • إذا أردت تشغيل بعض البرامج النصية عبر مساحات العمل الخاصة بك ، فستفعل yarn workspaces run <script> .
  • إذا كنت تريد ملف قفل واحد ورافعة (هل الاثنان مرتبطان بالضرورة معًا؟) ، فسيكون هذا هو الجذر package.json :
    json "workspaces": { "packages": ["packages/*"], "hoistDependencies": true }
  • إذا كنت ترغب في ترحيل ملفات القفل الحالية إلى بنية مرفوعة ، فستقوم بتشغيل yarn workspaces hoist-dependencies .

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

ماذا تعتقد؟

أعتقد أن المشكلة التي يعالجها طلب الميزة هذا هي نفسها الموجودة في # 4521. من المؤكد أن الأمر الذي يقوم بفعل ما يصفه @ johannes-scharlach بشكل أساسي سيكون أكثر جدوى من ملف قفل لكل مساحة عمل.

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

ما رأيك في أن تكون مساحات عمل Yarn مجرد نواة صغيرة - إعلان عن الحزم دون أي وظائف محددة

لن تتغير مساحات العمل بشكل جذري ، أعتقد أننا راضون عن واجهتهم الحالية.

إذا كنت ترغب في تشغيل بعض البرامج النصية عبر مساحات العمل الخاصة بك ، فستفعل yarn workspaces run <script>

هذا ممكن بالفعل (v1.10 ، # 6244).

إذا كنت ترغب في ترحيل ملفات القفل الحالية إلى بنية مرفوعة ، فيمكنك تشغيل yarn workspaces hoist-dependencies .

نظرًا لأننا لن نغير واجهة مساحة العمل ، فسيكون العكس ( dehoistDependencies ).

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

في هذه الحالة ، أعتقد أنه من الأفضل حل حالة الاستخدام ("تثبيت التبعيات في حزمة معينة فقط") من خلال تمديد yarn --focus .

أعتقد أن السؤال الأساسي هو ما إذا كان الرفع وملف واحد yarn.lock ضروريان تمامًا لمساحات العمل. أعني ، ما الذي يميزهم حقًا أم أنه "مجرد" الميزة الأولى التي حصلوا عليها تاريخيًا؟

على سبيل المثال ، في حالة الاستخدام الخاصة بنا ، سيكون أفضل سلوك افتراضي لمساحات العمل هو:

  • الرافعة node_modules في وقت التطوير لتحقيق الكفاءة.
  • احتفظ بملفات yarn.lock للبناء (نحن نبني حزمًا محددة في Docker ، وهو شيء ذكره الأشخاص الآخرون في هذا الموضوع أيضًا) وأيضًا حتى تتمكن الحزم من قفل إصداراتها المحددة. راجع أيضًا # 6563.
  • قم بتشغيل البرامج النصية عبر yarn workspaces run <script> حتى لو لم تكن بحاجة (أو يجب عليك تجنب) الرفع.

يمكن تعطيل الرفع باستخدام nohoist و run من خلال عدم استخدام الأمر فقط ولكن لا يمكن "تعطيل" الملف الواحد yarn.lock و أنا ' لست متأكدًا مما إذا كانت ميزة أساسية لا يمكن تعطيلها أو إذا لم يتم طلبها بشكل كافٍ حتى الآن :)

أعتقد أن أفضل طريقة لحل هذا هو الحصول على yarn install --app-mode package@version

بهذه الطريقة ، يمكنك ببساطة نسخ ملفات قفل مساحة العمل عند نشر تطبيقك في إصدار معين ، والتثبيت في app-mode سيحترم ملف القفل المجمع.

لا يتعين على الغزل تثبيت ملف القفل بالكامل ؛ يجب أن يكون قادرًا بسهولة على استخراج جزء من مخطط التبعية المرتبط بهذه الحزمة فقط.

في الواقع ، قد يكون من السهل القيام بذلك يدويًا حتى الآن:

  • قم بتنزيل الحزمة المضغوطة من التسجيل مباشرة (الغزل ليس له ما يعادله ، npm يفعل: npm pack package@version )
  • استخراج gzip إلى node_modules / package
  • cd في node_modules / package
  • تشغيل تثبيت الغزل - الإنتاج من هناك (سيحترم ملف القفل المجمّع)

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

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

حالة استخدام مشابهة جدًا من samuela هنا! هذا سيكون مفيد للغاية!

قد تبدو حالة الاستخدام الخاصة بي مضحكة مقارنة بالأخرى "الحقيقية". لكن لديّ monorepo لبعض الأدوات - في هذه الحالة ، خطافات التفاعل - داخل packages/* .

لدي مساحة عمل ثانية بجوار packages/* ، وهي local/* . هذا في الواقع موجود على gitignore ، والفكرة هي أن المطورين في الشركة قد يفعلون ما يحلو لهم هناك ، على سبيل المثال وضع تطبيقات create-react-app هناك واختبار الخطافات أثناء التطوير.

الآن ، على الرغم من أن حزم local/* موجودة على gitignore ، فإن الجذر yarn.lock ببساطة منتفخ وملوث - وتم تسجيله في git - بسبب مساحات العمل المحلية.

ما أتمناه هو طريقة لتحديد أن بعض مساحات العمل يجب أن تستخدم بعض ملفات القفل المحددة ، على سبيل المثال ، بعض الخرائط مثل:

  "workspaces": {
    "packages": [
      "packages/*",
      "local/*"
    ],
    "lockfiles": {
      "local/*": "./local.yarn.lock"
    }
  }

أو حتى طريقة لتحديد "لا تضع أي شيء من مساحة العمل هذه في ملف القفل على الإطلاق".

لكن نعم ، لا تعد حالة استخدامي خطيرة في المقام الأول :)

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

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

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

سبب آخر لوجود خيار لإنشاء ملفات قفل لكل مساحة عمل: يرفض محرك تطبيقات Google تشغيل خدمة Node بدون ملف قفل (NPM / Yarn). هذا مطورون ممتازون من جانبهم ، لكنه ألم لنا. حتى الآن الخيارات المتوفرة لدينا هي:

  • انشر الكل مع env vars للإشارة إلى الخدمة التي نعنيها وقم بتعديل yarn start (نقطة الدخول الوحيدة المدعومة) إلى الفرع على أساس متغيرات env
  • اطلب من البرنامج النصي للبناء نسخ ملف القفل الرئيسي إلى كل مساحة عمل ونشر الخدمة التي نهتم بها فقط. (شكرًا @ johannes-scharlach)

في النهاية ، أعتقد أن الأمر yarn install --workspace-lockfile الذي يتم إنشاؤه لكل ملفات قفل مساحة العمل سيكون الحل الأفضل.

سيساعدنا أيضًا وجود خيار لملفات قفل مستوى الحزمة. حالة الاستخدام الخاصة بنا مختلفة قليلاً ، فنحن نجرب طريقة جديدة لإدارة التبعيات المحلية.

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

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

لكننا واجهنا مشكلة واحدة لا يمكننا حلها ، ولا يؤدي تحرير التبعيات إلى تحديث ملف قفل الغزل المحلي ، بل يقوم دائمًا بتحديث الملف الجذري للريبو الأحادي الفارغ الذي لا نقوم بتحديث التبعيات عليه (يحتوي على كل شيء تحت /packages gitignored.

سيكون وجود خيار عدم رفع ملفات القفل على جذر الريبو الأحادي أمرًا رائعًا وجعلهم يكتبون على مستوى الحزمة.

كملاحظة ، صادفت أيضًا مشكلات النشر والبناء حول Docker التي ذكرها الآخرون وهذا من شأنه أن يحل ذلك أيضًا!

ستكون هذه الميزة ذات قيمة كبيرة بالنسبة لي أيضًا. في حالتي لدي monorepo مع بعض الحزم المنتشرة على منصات مختلفة. أحدهما هو تطبيق Next.js المنشور مع Now.sh والآخر عبارة عن مجموعة من الوظائف السحابية المنشورة في Firebase.

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

أود أيضًا أن أكون قادرًا على تمكين ملفات yarn.lock في كل مساحة عمل.

أدرك أن مساحات عمل الغزل مخصصة في الغالب للأحادية ، ولكن حالة الاستخدام الخاصة بنا تشبه إلى حد كبير حالة LeeCheneler .

في الأساس ، أنشأنا مكتبة مكونات React التي نستخدمها كتبعية في مشاريع مختلفة (تحتوي جميعها على وحدات إعادة الشراء الخاصة بها). باستخدام مساحات عمل الغزل ، يمكننا بسهولة الرجوع إلى الإصدار المحلي من مكتبة المكونات وإجراء تغييرات تنتشر على الإصدار المحلي من مشاريعنا الأخرى بسرعة. لا نحتاج أيضًا إلى تعديل package.json عندما نضغط على الإنتاج لأن التبعية library: "*" تعمل بدون أي تغييرات. مشكلتنا الوحيدة هي أنه بدون ملفات أقفال الغزل ، يمكن أن تنتهي إصدارات الإنتاج لكل مشروع باستخدام إصدارات مختلفة من الحزم.

يجب أن أتخيل أن هذه المشكلة قد تكون شائعة بين مطوري الحزم الذين يستخدمون مساحات عمل الغزل.

هناك مشكلة أخرى مهمة في ملف قفل المستوى الأعلى وهي أنه يكسر التخزين المؤقت لطبقة Docker. عادةً ما يكون المرء قادرًا على تحسين التخزين المؤقت لـ Docker عن طريق نسخ الحزمة.json و yarn.lock أولاً. إذا لم ير Docker أي تغييرات في هذه الملفات ، فسيستخدم طبقة سابقة. إذا كان ملف القفل هذا واحدًا لكامل monorepo ، فإن أي تغيير في أي حزمة يبطل ذاكرة التخزين المؤقت. بالنسبة لنا ، ينتج عن ذلك خطوط أنابيب CI / CD بطيئة بشكل يبعث على السخرية حيث يتم إنشاء كل حزمة بدون ذاكرة التخزين المؤقت. هناك أدوات أخرى ، مثل Lerna ، تتحقق من تغييرات الحزمة لتشغيل نصوص برمجية معينة. ينكسر هذا أيضًا نظرًا لأن تغيير التبعية في ملف القفل قد لا يتم التقاطه لكونه في المستوى الأعلى.

آسف لإثارة هذه المشكلة (القديمة قليلاً) ولكن لدي أيضًا حالة استخدام سيكون ذلك مفيدًا فيها. لديّ 10 أو نحو ذلك من الخدمات المصغرة التي يتم استضافتها وتطويرها بشكل مستقل ولكن سيكون من الجيد أن يكون لديك مستودع مساحة عمل مركزي حيث يمكنك كتابة yarn install لتثبيت التبعيات في جميع المجلدات ثم تشغيل yarn start لتشغيل برنامج نصي سيبدأ تشغيل جميع الخدمات المصغرة. هذا شيء يمكن القيام به باستخدام برنامج نصي بسيط نسبيًا ولكن يبدو أيضًا أنه يمكن تنفيذه باستخدام مساحات عمل الغزل ولكن لم أتمكن من تشغيله مع احترام الغزل.

nahtnam أعتقد أن فكرة Yarn 1.x monorepo مختلفة قليلاً. لا يتعلق الأمر بالمشاريع المستقلة تحت سقف واحد ، بل يتعلق أكثر بمشروع كبير فردي به بعض مكوناته مكشوفة (تسمى مساحات العمل). هذه المكونات ليست مستقلة تمامًا ، ولكن يمكن استخدامها على النحو التالي: مترجم Babel ككيان أكبر و preset-env كوحدة فرعية. أيضًا ، فهي متجانسة بمعنى أن تبعياتها موحدة: إذا كانت بعض الحزم تعتمد على core-js ، فيجب أن تكون نفس الإصدار core-js في كل واحدة منها ، لأنه لا يمكنك قفل إصدارات مختلفة بملف قفل جذر واحد ، وليس من المنطقي أن تعتمد أجزاء المشروع على إصدارات مختلفة. ولأنه مشروع واحد ، يتم ربط جميع مكوناته تلقائيًا بالجذر node_modules ، وهو أمر غريب بالنسبة للمشاريع المستقلة تمامًا.

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

السؤال الوحيد هو ما الأداة التي ستساعد في تشغيل البرامج النصية. قد تكون Lerna إجابة لأنها غير مرتبطة بالغزل.

@ the-spyke ليس هذا فقط. yarn workspaces يحل أيضًا ، ويربط الوحدات من أجل التطوير بنفس الطريقة التي يعمل بها npm link ، وهذا هو السبب الرئيسي لاستخدامنا للوحدات. npm link لا يعمل بشكل جيد في بعض الحالات.

@ the-spyke شكرا لك! لسبب ما ، اعتقدت أنه تم قلبه (مساحات عمل lerna vs yarn). لقد بحثت في lerna ويبدو أنها تحل مشكلتي

انتهى بي الأمر باستخدام مساحات العمل لكل مشروع واحد أعمل عليه ، نظرًا لمدى سهولة الحصول على حزمة منفصلة utilities يمكنني تحديثها عند الحاجة (على الرغم من نشرها) ، وحقيقة ذلك لست مضطرًا إلى إعادة تثبيت التبعيات إذا كنت أرغب في تفريق بعض الحزم (السماح لي أساسًا بالعمل على فرعين في نفس الوقت ، وهو الأمر الذي لم يسمع به من قبل) ، وكلما أردت استخدام حزمة من utilities (الذي يتضمن معظم الأشياء التي أستخدمها عادةً) ، يمكنني استخدامه على الفور دون إضافته إلى package.json من الحزمة الثانية (ولكن من الواضح أن هذه فكرة جيدة في حالة التثبيت المنفصل ، وهي مطلوبة لواردات IDE التلقائية) ؛ كل شيء يعمل فقط. @ the-spyke يشير إلى نقطة جيدة ، ربما independent projects under one roof ليس الغرض من مساحات العمل ، ومع ذلك يبدو أن هذا ما أفعله هنا إلى حد كبير: لدي مستودع واحد monorepo-base ، والذي يستثني المجلد packages ، في حين أن كل مجلد أقل من packages هو مستودع git مستقل ومستقل.
image
بالطبع هذا يقودني إلى موضوع هذا الموضوع ؛ نظرًا لأنني لا ألتزم بجميع الحزم باعتبارها ريبو واحدًا ، فإن مستوى الجذر yarn.lock لا معنى له. لقد كنت أستخدم --no-lockfile لتثبيت كل شيء ، وواجهت مؤخرًا مشكلة في الإصدارات المتضاربة من class-validator . في الوقت الحالي ، سأقفل جميع الأقسام في إصدارات محددة (بصراحة ، هذا المستوى من التحكم أكثر منطقية بالنسبة لي) وأرى كيف يعمل. سأقرأ المداس بالكامل مرة أخرى ، ربما هناك بعض النصائح التي سأتمكن من استخدامها لحالة الاستخدام الخاصة بي.

ملاحظة.
yarn why لا يعمل بدون ملف lockfile لأحد ، وقد لاحظت أن بعض الأشخاص يذكرون مشاكل مع App Engine. أفترض أنه في حالة كون كل حزمة عبارة عن ريبو منفصل ، يمكن إنشاء ملف القفل في كل مرة عند التثبيت (بدون إضافته إلى VCS)؟ لست متأكدا من تلك الحالة المحددة.

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

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

إليك الحل الذي توصلنا إليه - بأقل تأثير على سير عمل Docker الحالي.

  1. ln project/yarn.lock packages/package1/yarn.lock - أنشئ ارتباطًا رمزيًا ثابتًا من الجذر yarn.lock في كل حزمة.
  2. أضف COPY yarn.lock . لكل packages/package1/Dockerfile
  3. yarn install داخل Docker

مزايا :

  • لا يتعين عليك نسخ monorepo بالكامل في طبقة صورة
  • لا يتعين عليك دمج Dockerfiles على مستوى الحزمة في Dockerfile واحد في الجذر
  • يلبي بشكل أساسي متطلبات ملفات قفل مساحة العمل

العيوب :

  • --frozen-lockfile لا يعمل. نظرًا لأن حزم مساحات العمل غير مضمنة في yarn.lock ، لذلك يرى الغزل حزمة قمت "بإضافتها" إلى package.json غير الموجودة في yarn.lock

هذا عيب بسيط بغض النظر ، حيث يمكنك الالتفاف عليه من خلال تنفيذ yarn --frozen-lockfile كخطوة أولى في خط أنابيب CI / CD الخاص بك

يحرر:
جانبا ، أعتقد حقًا أن مستندات الغزل عند التثبيت يمكن أن تكون أوضح قليلاً مع كيفية استخدام ملف القفل بواسطة عملية تحليل الحزمة.

يحرر:
لذلك اتضح أن git لا يدعم الروابط الصلبة في الواقع ، فهو يدعم فقط الروابط الرمزية الناعمة ، لذلك لن تعمل هذه الإستراتيجية.

بديل آخر هو ببساطة استخدام أداة githook المسبقة لنسخ yarn.lock في كل مساحة من مساحات العمل الخاصة بك ... إنها ليست مثالية لأنها لا تزال تسمح بالمشكلات عند النشر من جهازك المحلي.

@ dan-cooke شكرًا جزيلاً على أفكاركم ، أقدر ذلك كثيرًا!

@ dan-cooke ، يكسر هذا التخزين المؤقت لطبقة Docker لأن التبعية الجديدة في أي مساحة عمل ستبطل طبقة التثبيت لجميع ملفات Dockerfiles.

migueloller إذا كان يجب ألا تتغير طبقة التثبيت ، فلا يجب عليك استخدام ملف قفل واحد لجميع الحزم. إن تسطيح ورفع التبعيات في قائمة عملاقة واحدة هو الغرض الكامل من مساحات العمل. إنه ليس مثل "يكسر" ذاكرة التخزين المؤقت لـ Docker ، ذاكرة التخزين المؤقت غير صالحة لأن التبعيات الحقيقية غير محددة في package.json ، لذا فإن الكود النهائي لحزمتك يعتمد على محتوى yarn.lock . كنتيجة لذلك ، تحتاج إلى إعادة بناء جميع الحزم عند كل تغيير في yarn.lock ويقوم Docker بعمل كل شيء بشكل صحيح. وهو ليس مثل where every package is built without the cache لأن جميع البنيات يمكن أن تعيد استخدام الطبقة بـ yarn install (ربما ستحتاج إلى إعداد هذا).

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

وحتى ذلك الحين ، فإنه ثمن ضئيل يجب دفعه (لنا) مقابل التبعيات القابلة للتكرار في Docker

@ the-spyke ، في الواقع. ولهذا السبب تتعلق هذه المشكلة بوجود ملف قفل فردي لكل حزمة. بهذه الطريقة ، يتم إبطال الطبقة المخزنة مؤقتًا فقط عندما تتغير تبعيات الحزمة وتكون مستقلة عن الحزم الأخرى.

ربما يجدر أيضًا نقل هذه المناقشة إلى npm نفسها ، والتي تدعم مساحات العمل أيضًا بدءًا من الإصدار 7.0 ..

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

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

لقد أهدرت أكثر من ساعات كافية في آخر التحديثات في الماضي في مناسبات متعددة ؛ سأجرب استخدام lockfile في monorepo ، لأنني أفضل التعامل مع تعارضات الدمج والصداع التنظيمي ، بدلاً من الأخطاء غير المرئية التي تسببها التحديثات الطفيفة.

أعلاه ، إنني أتطلع بشدة إلى أي تقدم بشأن هذه المسألة

migueloller - ملفات القفل الفردية تعني فردي الغزل Monorepos. لا يمكنك الحصول على ملف قفل لمساحة العمل لأنه يكسر التوحيد في Monorepo. إذا كنت ترغب في القيام بذلك ، فأنت تبتعد عن الفكرة الأصلية لـ Yarn Monorepo: إنها تتعلق بالتوحيد والرفع وتقليل الأقسام في قائمة مسطحة في الجذر بدلاً من وجود إصدارات مختلفة (وحتى مجموعات فرعية كاملة) في مساحات عمل مختلفة .

@ the-spyke لكن المشكلة الأصلية تدور حول العكس تمامًا. ملف قفل لكل مساحة عمل.

لم أفهم كيف لا يمكنك الحصول على ملف قفل لكل مساحة عمل.

انه يكسر deps التوحيد في Monorepo؟ بالتأكيد من أجل التنمية. لكن الغرض الكامل من التبعيات المشتركة يخرج من النافذة عندما يتعين عليك نشر خدمات صغيرة خفيفة الوزن من كل من مساحات العمل الخاصة بك

لا تكون الأقسام المشتركة والمرفوعة منطقية إلا في التنمية.

لكي تعيش مساحة العمل في Docker ، فإنها تتطلب ملف قفل.

@ dan-cooke كما ترون ، واجهت هذه المشكلة في 2018 أيضًا ، لكن الآن لدي رأي مختلف.

أنت تقول Docker and Microservices. ولكن ماذا لو قمت بتطوير حزمة عادية npm ؟ ليس لدي شجرة تبعيات فرعية production لتثبيتها ، لأنه سيتم توفيرها بواسطة المستخدم النهائي وفقًا لمواصفات dependencies الخاصة بي. لذا ، ما أريده هو زيادة خبرتي في التطوير إلى الحد الأقصى ، وهذا ما تفعله مساحات Monorepos و Yarn بشكل مثالي.

في نفس الوقت ، إذا كنت تقوم بتطوير خدمات مصغرة (MS) ، فهناك حالتان محتملتان:

  1. مشاريع مستقلة. بعض أمراض التصلب العصبي المتعدد قيد التطوير ، وبعضها لم يتم التطرق إليه منذ سنوات. في هذه الحالة هم مستقلون تمامًا. من الممكن أن يكون لديك UserService باستخدام [email protected] و MessagesService باستخدام [email protected] . ليس هذا هو العالم السهل حيث تقوم فقط بربط المجلدات من مساحات العمل بالجذر node_modules . لذلك ، لا جدوى من وجود ملف قفل الجذر. إنشاء ملفات منفصلة (جذور) وإدارتها بشكل مستقل. هذا يسمى Multirepo في مستندات الغزل. ولكن ما تقوله الآن هو "أريد تشغيل المهام في مجلدات مختلفة من المجلد الجذر للراحة". وهذا موضوع مختلف تمامًا.

  2. المشاريع ذات التبعيات الموحدة مثل Jest / Babel / إلخ. هذا هو الغرض من إنشاء مساحات العمل ، ولكن في MS هناك متطلبات إضافية. أثناء مراحل CI مثل الفحص والاختبار ، تعمل جميعها بشكل جيد لأنها تعمل بنفس الطريقة التي تعمل بها على جهاز المطور: الأجزاء المثبتة بواسطة Yarn في وحدات عقدة الجذر ويتم تسويتها. فقط مع إضافة أنك ربما تقوم بتخزين مرحلة yarn install مؤقتًا لتسريع عمليات الإنشاء المتزامنة.

    في الإنتاج ، الأمر مختلف تمامًا: بدءًا من ذلك ، فأنت تحتاج فقط إلى أقسام لمساحة عمل واحدة وتنتهي بكيفية تثبيت حزمة utils ؟ هل يجب ربطها أو تنزيلها على أنها تاربال؟ لذلك ، ما تحتاجه حقًا هو عدم وجود ملفات قفل لكل مساحة عمل ، ولكن وجود أمر مثل yarn install --prod <workspace> يمكنك تشغيله لتحديد مساحة العمل وسوف يقوم بتثبيت أقسام الإنتاج فقط وفي نفس الوقت تجاهل مساحات العمل الأخرى غير المشار إليها. كما لو أن data WS الخاص بي يعتمد على utils WS ، لكن ليس على logging WS ، فإن logging نفسه ويجب ألا تظهر مستودعاته في node_modules . نتيجة مماثلة ، ولكن أسلوب مختلف تمامًا "لقفل الملف لكل مساحة عمل".

    إذا كنت تنشر حزم إنشاء في مستودع (npm ، Arifactory ، GutHub) ، فيمكنك الحصول على سلوك مشابه فقط عن طريق نسخ ملف القفل إلى مساحة العمل والقيام بـ yarn install --prod هنا. يجب أن يحذر من ملف قديم ، ولكن بدلاً من إعادة إنشائه من الصفر بإصدارات جديدة ، يجب فقط إزالة الأجزاء الزائدة منه (تمت تجربته فقط ويبدو شرعيًا). يجب أن تكون أفضل وأكثر قوة مع استخدام Offline Mirror.

    وفي النهاية ، تم تنفيذ مساحات العمل المركزة بالضبط لـ Multirepos.

لذا ، ما كنت أقوله أنه ربما لا تبدو المشكلة كما هي.

@ the-spyke
أرى ما تقوله. أعتقد أنه بالتأكيد يتعلق بكيفية تحقيق هذه النتيجة. ربما لا يكون ملف القفل في مساحة العمل هو في الواقع أفضل طريقة لتحقيق النتيجة المرجوة. أنت تصنع بعض النقاط الجيدة.

إنه بالتأكيد ليس حل "مقاس واحد يناسب الجميع" على أي حال

@-spyke الخاص بك طرح نقاط جيدة. ربما يجب التفكير في المشكلات التي تم تصميم مساحات عمل الغزل لحلها وإذا كان استخدامها لإدارة monorepos الكبيرة يتماشى مع هذا التصميم.

لدي فضول لمعرفة كيفية حل سيناريو مثل هذا:

.
└── packages
    ├── app1
    ├── app2
    ├── lib1
    ├── lib2
    └── lib3

lib3 مكتبة مشتركة ويعتمد عليها app1 و app2 . lib1 فقط بواسطة app1 و lib2 يُستخدم فقط بواسطة app2 . بناءً على اقتراحاتك ، يجب أن يكون lib1 و app1 في مساحة العمل الخاصة بهم مع ملف القفل الخاص بهم ونفس الشيء مع lib2 و app2 . الآن ، السؤال هو ما يجب فعله بـ lib3 إذا كان _both_ app1 و app2 يعتمد عليه؟ ربما يمكن للمرء أن يفعل ذلك بحيث تضيف مساحتا العمل ( app1 و app2 ) lib3 إلى مساحة العمل الخاصة بهم ثم تشغيل yarn install في كل تطبيق؟ هل يسمح الغزل بهذا؟ هل سيكون هناك أي تعارض إذا أراد أحد تشغيل كل من app1 و app2 في التطوير محليًا (ربما app1 هو تطبيق React و app2 a GraphQL API) ؟ هذا يبدو وكأنه يمكن أن يعمل.

السؤال التالي الذي يجب طرحه سيكون "كيف يحصل المرء على فوائد الرفع بهذه الطريقة؟" على سبيل المثال ، إذا كان app1 و app2 يشتركان في الكثير من التبعيات الشائعة ، فسيكون من الجيد رفعها. أستطيع أن أرى كيف قد يكون هذا خارج النطاق ، رغم ذلك ، وهي مشكلة يجب حلها بواسطة Yarn PnP (لا ينسخ الملفات إلى node_modules وبدلاً من ذلك يحتوي على ذاكرة تخزين مؤقت مشتركة).

سأقوم بإعطاء هذه اللقطة وسأقوم بالإبلاغ عنها. إذا انتهى الأمر بالنجاح ، فربما كنا نستخدم مساحات عمل Yarn بشكل خاطئ طوال الوقت ...

تحرير: لقد جربته ، وهو يعمل.

لقد غيرت موقفي الآن وأدركت أنه في حين أن وجود ملف قفل فردي لكل مساحة عمل قد يكون أول ما يتبادر إلى الذهن عند إدارة monorepo بالكامل باستخدام مساحات عمل Yarn ، فقد لا يكون السؤال الصحيح. قد يكون السؤال الأفضل هو "هل مساحات عمل الغزل مصممة لإدارة monorepo؟". الجواب ، كالعادة ، "يعتمد".

إذا كنت Babel ولديك فريق واحد يعمل على monorepo وكل شيء من المفترض أن يتغير بخطوة ثابتة ، إذن نعم ، هذا ما تم تصميم مساحات عمل Yarn من أجله. ولكن إذا كنت مؤسسة ذات فرق متعددة وكنت تستخدم monorepo ، فمن المحتمل أنك لا تريد إدارة monorepo بالكامل باستخدام جذر مساحة عمل Yarn واحد. ربما تريد فقط استخدام السلوك الافتراضي لـ Yarn أو جذور مساحة عمل Yarn المتعددة داخل monorepo. سيتم تحديد ذلك من خلال التطبيقات التي تقوم بإنشائها وعدد الفرق الموجودة وما إلى ذلك.

بالنسبة لنا ، أصبح من الواضح أنه بالنسبة لكل كيان قابل للنشر (في حالتنا يوجد Dockerfile) ، نريد الحصول على yarn install منفصل لكل كيان (سواء كان جذرًا للعمل أم لا). يوفر هذا وضوحًا حول ملكية الكود ، ويسمح بعمليات النشر المعزولة التي تحدث في إيقاعات مختلفة ، ويحل مشكلات التخزين المؤقت مع lockfiles و Docker ، وما إلى ذلك. هناك بعض الجوانب السلبية لهذا ، على الرغم من:

  • ماذا عن حزم node_modules المكررة؟ هذه فئة شائعة من المشاكل مع monorepos وعلى الرغم من أن مساحات عمل Yarn تساعد في الرفع ، إلا أنها ليست حلاً عامًا للأحادية. ومع ذلك ، هناك حلول أخرى. على سبيل المثال ، يعتني Yarn PnP بهذا. يمكنك أيضًا استخدام Lerna بدون Yarn واستخدام الخيار --hoist .
  • ماذا عن فائدة تشغيل الأمر عبر مساحات العمل أثناء التطوير؟ مرة أخرى ، تتيح لك مساحات عمل Yarn القيام بذلك ، لكن هذا لا يعني أنه يجب على المرء أن يجعل monorepo بأكمله جذر مساحة عمل Yarn. سيكون بناء الأدوات والبرامج النصية اللازمة مختلفًا لكل فريق ويعتمد على monorepo الخاص بهم. ربما لم يتم تصميم مساحات عمل الغزل على أنها عداء مهام monorepo. قد يحاول المرء ثني مساحات عمل Yarn قليلاً للقيام بهذه المهمة (على سبيل المثال ، تشغيل البرامج النصية NPM عبر monorepo باستخدام yarn workspace ... ) ولكن من المهم أن تضع في اعتبارك أن جذر مساحة عمل واحد لكامل monorepo ربما لن يمنحك ما تحتاجه إلا إذا كنت مثل Babel و Jest و React وما إلى ذلك.

هناك مجموعة أخرى كاملة من المشاكل التي تأتي مع تشغيل monorepo. على سبيل المثال ، ماذا عن تتبع التبعيات وإعادة بناء الأشياء التي تغيرت فقط لتوفير الوقت في CI؟ يمكن أن تساعد مساحات عمل الغزل هناك من خلال السماح لك بالاستعلام عن الرسم البياني للتبعية. يقوم Lerna بهذا ، على سبيل المثال ، للسماح بتشغيل الفرز الطوبولوجي للأوامر. يتيح لك Yarn v2 الاستعلام عن الرسم البياني للتبعية أيضًا. يقوم مدير الحزم PNPM بذلك أيضًا. لكنني أزعم أنه اعتمادًا على مدى تعقيد monorepo ، قد يرغب المرء في تجربة الأدوات المصممة لذلك (وليس مديري الحزم) مثل Bazel و Pants و Buck وما إلى ذلك.

migueloller من متطلباتك ، أرى أنك لست بحاجة إلى حزم مستقلة تمامًا أو أشياء غريبة أخرى ، فأنت أيضًا تريد تثبيت مطور أقل حجماً. في مثل هذه الحالة ، يجب أن تبدأ بـ Yarn Monorepo العادي: جذر واحد وجميع الحزم كمساحات عمل. سيكون لديك أوقات تثبيت أسرع ، واستخدام أقل للقرص ، و app1 سيستخدم lib1 و lib3 . سيكون الجانب السلبي الوحيد في كثير من الأحيان هو إبطال ذاكرة التخزين المؤقت CI لأن إضافة devDep إلى lib1 سيؤدي إلى تحديث yarn.lock . لكن عادةً لا تقوم بتحديث التبعيات التي غالبًا ما تقلق كثيرًا بشأن هذه المقايضة.

lib1 قد تعتمد على lodash@^4.5.0" and lib2 may depend on lodash@^4.10.0 ". الحالة في لMonorepo تريد نسخة واحدة من lodash المستخدمة، لذلك سيقوم Yarn بتثبيت أحدث شيء متوافق مع كل من المحدِدين مثل `` [email protected] "

هناك أيضًا مواقف تقوم فيها فرق مستقلة بتطوير مشاريع مستقلة. في هذه الحالة ، قد يرغب proj1 في البقاء عند [email protected] مع proj2 وجود [email protected] وتحديث ذلك بإيقاعهم الخاص. بالطبع ، يمكنك تحقيق ذلك باستخدام محددات أكثر صرامة مثل lodash@~4.5.0 ، ولكن هذا قد يستمر في تحديث تبعية المستوى الثاني في وقت مبكر جدًا. لذلك ، قد تكون هذه المشاريع بشكل عام غير ذات صلة على الإطلاق ، لقد صادف أن تكون داخل مستودع git واحد. في هذه الحالة ، لا يوجد سبب لربطها بـ Yarn Monorepo واستقلال المقايضة لملف قفل مشترك. فقط عاملهم كما هم: مشاريع منفصلة عن حياتهم المستقلة. وهذا ما يسمى Multirepo. في Unix ، تكون جميع أدلةك أقل من / ، لكن هذا لا يعني أن جميع مشاريع JS الممكنة على جهاز الكمبيوتر الخاص بك يجب أن تكون Monorepo :-)

لا يرتبط إنشاء صورة Docker بأدنى حد ممكن للاستخدام الإنتاجي تمامًا بـ Yarn ، ولكن يمكنك إجبار Yarn على إعادة استخدام أداة تطوير تسمى yarn.lock وتساعدك في هذه المهمة أيضًا.

@ the-spyke ، في هذا المثال ، استخدمت 3 مساحات عمل فقط ولكن في الريبو الفعلي لدينا أكثر من 20 مساحة عمل مع مجموعة من المكتبات وأحمال العمل المنشورة لكل من الواجهة الأمامية والخلفية. الطريقة التي أراها الآن هي أن لدينا monorepo (أو ما تسميه multirepo) حيث سيكون من المنطقي على الأرجح أن يكون لديك العديد من جذور مساحة عمل Yarn مع ملفات قفل مستقلة. نحن نفكر في استخدام وحدة قابلة للنشر كوحدة فصل ، تتماشى بشكل جيد مع ملفات القفل.

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

{
  "workspaces": [
    "../lib1",
    "../lib3"
  ]
}

لدينا نفس حالة الاستخدام مثل migueloller وإحدى الأفكار المحتملة هي أن يدعم Yarn مجموعات متعددة من مساحات العمل ، مثل هذا:

{
  "workspaces": {
    "frontend-app": ["frontend", "common"],
    "backend-app": ["backend", "common"]
  }
}

سيحتفظ الغزل بملفي قفل إضافيين (أتخيل أن yarn.lock سيظل موجودًا):

.
└── monorepo/
    ├── yarn.frontend-app.lock
    ├── yarn.backend-app.lock
    └── packages/
        ├── frontend
        ├── backend
        └── common

عند إنشاء صورة Docker ، على سبيل المثال للواجهة الأمامية ، سننشئ سياقًا (على سبيل المثال ، عبر القطران ) يتضمن هذا:

.
└── <Docker build context>/
    ├── yarn.frontend-app.lock
    └── packages/
        ├── frontend
        └── common

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

(تم نشر شيء مشابه هنا أيضًا).

يبدو أنك لست بحاجة إلى ملف قفل لكل مساحة عمل ولكنك تحتاج بدلاً من ذلك إلى node_modules لكل مساحة عمل للنشر

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

قد يكون من الجدير بالذكر أنه يمكن القيام بذلك في أرض المستخدم. باستخدام الحزمة @yarnpkg/lockfile يمكن للمرء تحليل ملف تأمين المستوى الأعلى ، ثم باستخدام yarn workspaces info يمكن للمرء تحديد تبعيات مساحة العمل. باستخدام هذه المعلومات ، جنبًا إلى جنب مع package.json لكل مساحة عمل ، يمكن للمرء إنشاء ملف قفل لكل مساحة عمل. بعد ذلك ، يمكن للمرء إعداد ذلك كبرنامج نصي postinstall في الريبو للحفاظ على مزامنة ملفات القفل الفردية مع المستوى الأعلى.

قد أتعرض للطعن في بناء هذا وأقوم بإبلاغ النتائج التي توصلت إليها.

يبدو أنني وجدت للتو هذا التطبيق وإن كان لـ pnpm: @ pnpm / make -edicated-lockfile

أتمنى أن يساعد هذا 👍

حاجتي لهذا السلوك (تعيين الإصدار لكل مساحة عمل ، ولكن لا يزال لدي ملفات قفل في كل حزمة) هو أن لديّ monorepo متداخلة ، حيث يتم تصدير شجرة فرعية إلى ريبو آخر تمامًا ، لذلك يجب أن تظل مستقلة. الآن أنا عالق مع lerna / npm وبعض المنطق المخصص لمحاولة الخروج من الإصدارات. سيكون لطيفًا إذا كان بإمكان الغزل (أعتقد أن الإصدار 2 ، نظرًا لأن هذا هو المكان الذي يكمن فيه الدعم المتداخل؟) أن يديرها جميعًا مرة واحدة ، ولكن اترك المجموعة الفرعية الصحيحة من التثبيت العالمي في كل منها.

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

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات