Typescript: دعم المشاريع "متوسطة الحجم"

تم إنشاؤها على ١٠ يونيو ٢٠١٥  ·  147تعليقات  ·  مصدر: microsoft/TypeScript

لقد دفعني الاستماع إلى nycdotnet للتعامل مع هذا الأمر. شكرا ستيف. (راجع للشغل ، يمكنك التحقق من مقابلته الجيدة هنا: http://www.dotnetrocks.com/default.aspx؟showNum=1149)

بدأ الاقتراح هنا لأول مرة في عصور ما قبل التاريخ (حتى قبل # 11) ، عندما سارت الديناصورات في الأرض المحروقة. بينما لا يوجد شيء جديد في هذا الاقتراح ، في حد ذاته ، أعتقد أن الوقت قد حان لمعالجة هذه المشكلة. اقتراح ستيف نفسه هو # 3394.

المشكلة

حاليًا ، في TypeScript ، من السهل البدء والمضي قدمًا ، ونحن نجعل الأمر أسهل مع كل يوم (بمساعدة أشياء مثل # 2338 والعمل على System.js). هذا رائع. ولكن هناك بعض العقبات مع نمو حجم المشروع. لدينا حاليًا نموذج عقلي يسير على ما يلي:

  • المشاريع الصغيرة الحجم: استخدم tsconfig.json ، واحتفظ بمعظم مصدرك في الدليل الحالي
  • المشاريع كبيرة الحجم: استخدم الإنشاءات المخصصة ، ضع المصدر في المكان الذي تريده

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

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

  • المشاريع الصغيرة الحجم: استخدم tsconfig.json ، واحتفظ بمعظم مصدرك في الدليل الحالي
  • المشاريع متوسطة الحجم: تلك التي تحتوي على بنى قياسية ومكونات مشتركة
  • المشاريع كبيرة الحجم: استخدم الإنشاءات المخصصة ، ضع المصدر في المكان الذي تريده

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

عرض

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

الأهداف

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

غير الأهداف

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

تصميم

لدعم المشاريع متوسطة الحجم ، نركز على حالة استخدام أحد ملفات tsconfig.json التي تشير إلى أخرى.

مثال على tsconfig.json اليوم:

{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true
    },
    "files": [
        "core.ts",
        "sys.ts"
    ]
}

قسم "التبعيات" المقترحة في tsconfig.json:

{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true
    },
    "dependencies": [
        "../common", 
        "../util"
    ],
    "files": [
        "core.ts",
        "sys.ts"
    ]
}

تشير التبعيات إلى إما:

  • دليل حيث يمكن العثور على tsconfig.json
  • A tsconfig.json مباشرة

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

كيف تعمل

يتم إنشاء التبعيات أولاً ، بالترتيب المذكور في قسم "التبعيات". إذا فشلت التبعية في البناء ، فسيخرج المترجم مع وجود خطأ ولن يستمر في بناء بقية المشروع.

عند اكتمال كل تبعية ، يتم توفير ملف ".d.ts" يمثل المخرجات للبنية الحالية. بمجرد اكتمال جميع التبعيات ، يتم بناء المشروع الحالي.

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

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

محددات

تعتبر إضافة دليل كعنصر تبعية لا يحتوي على tsconfig.json خطأ.

من المفترض أن تكون مخرجات التبعيات قائمة بذاتها ومنفصلة عن المشروع الحالي. هذا يعني أنه لا يمكنك ربط إخراج التبعية بالمشروع الحالي عبر tsconfig.json. يمكن للأدوات الخارجية ، بالطبع ، توفير هذه الوظيفة.

كما ذكرنا سابقًا ، تعتبر التبعيات الدائرية خطأ. في الحالة البسيطة:

أ - ب
\ ج

A هو "المشروع الحالي" ويعتمد على تبعيتين: B و C. إذا لم يكن لدى B و C تبعيات ، فإن هذه الحالة تافهة. إذا كانت C تعتمد على B ، يتم توفير B لـ C. لا يعتبر هذا دائريًا. ومع ذلك ، إذا كان B يعتمد على A ، فسيتم اعتبار ذلك دائريًا وسيكون خطأ.

إذا ، في المثال ، يعتمد B على C و C مستقل بذاته ، فلن يتم اعتبار ذلك دورة. في هذه الحالة ، سيكون ترتيب التجميع هو C ، B ، A ، والذي يتبع المنطق الذي لدينا لـ /// ref.

تحسينات / تحسينات اختيارية

إذا لم يتم إعادة بناء التبعية ، فسيتم تخطي خطوة بنائها وإعادة استخدام تمثيل '.d.ts' من البنية السابقة. يمكن توسيع هذا للتعامل إذا كان تجميع التبعيات قد بنى تبعيات ستظهر لاحقًا في قائمة "التبعيات" للمشروع الحالي (كما حدث في المثال الوارد في قسم القيود).

بدلاً من معالجة الدلائل التي تم تمريرها على أنها تبعيات لا تحتوي على tsconfig.json كحالات خطأ ، يمكننا اختياريًا تطبيق "الملفات" الافتراضية وإعدادات المشروع الحالي على تلك التبعية.

Committed Monorepos & Cross-Project References Suggestion

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

المستندات / blogpost العمل قيد التقدم أدناه (سيتم تعديل هذا بناءً على التعليقات)

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


مراجع المشروع

مراجع المشروع هي ميزة جديدة في TypeScript 3.0 تتيح لك هيكلة برامج TypeScript إلى أجزاء أصغر.

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

نقدم أيضًا وضعًا جديدًا لـ tsc ، علامة --build ، والتي تعمل جنبًا إلى جنب مع مراجع المشروع لتمكين عمليات إنشاء TypeScript بشكل أسرع.

مشروع مثال

دعنا نلقي نظرة على برنامج عادي إلى حد ما ونرى كيف يمكن لمراجع المشروع أن تساعدنا في تنظيمه بشكل أفضل.
تخيل أن لديك مشروعًا مكونًا من وحدتين ، converter و units ، وملف اختبار مطابق لكل منهما:

/src/converter.ts
/src/units.ts
/test/converter-tests.ts
/test/units-tests.ts
/tsconfig.json

تستورد ملفات الاختبار ملفات التنفيذ وتقوم ببعض الاختبارات:

// converter-tests.ts
import * as converter from "../converter";

assert.areEqual(converter.celsiusToFahrenheit(0), 32);

في السابق ، كان هذا الهيكل محرجًا إلى حد ما للعمل معه إذا كنت تستخدم ملف tsconfig واحدًا:

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

يمكنك استخدام ملفات tsconfig متعددة لحل بعض هذه المشكلات ، ولكن ستظهر مشكلات جديدة:

  • لا يوجد فحص مُحدّث مضمّن ، لذلك ينتهي بك الأمر دائمًا بتشغيل tsc مرتين
  • يؤدي استدعاء tsc مرتين إلى زيادة وقت بدء التشغيل
  • لا يمكن تشغيل tsc -w على ملفات تهيئة متعددة في وقت واحد

يمكن لمراجع المشروع أن تحل كل هذه المشاكل وأكثر.

ما هو مرجع المشروع؟

tsconfig.json لها خاصية جديدة من المستوى الأعلى ، references . إنها مجموعة من الكائنات التي تحدد المشاريع للرجوع إليها:

{
    "compilerOptions": {
        // The usual
    },
    "references": [
        { "path": "../src" }
    ]
}

يمكن أن تشير الخاصية path لكل مرجع إلى دليل يحتوي على ملف tsconfig.json ، أو إلى ملف التكوين نفسه (والذي قد يكون له أي اسم).

عندما تشير إلى مشروع ما ، تحدث أشياء جديدة:

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

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

composite

يجب أن يتم تمكين الإعداد الجديد composite للمشاريع المشار إليها.
هذا الإعداد ضروري لضمان أن TypeScript يمكنه تحديد مكان العثور على مخرجات المشروع المشار إليه بسرعة.
يؤدي تمكين علامة composite تغيير بعض الأشياء:

  • الإعداد rootDir ، إذا لم يتم تعيينه بشكل صريح ، يتم تعيينه افتراضيًا إلى الدليل الذي يحتوي على الملف tsconfig
  • يجب مطابقة جميع ملفات التنفيذ بنمط include أو مدرجة في مصفوفة files . إذا تم انتهاك هذا القيد ، فسيخبرك tsc بالملفات التي لم يتم تحديدها
  • يجب تشغيل declaration

declarationMaps

لقد أضفنا أيضًا دعمًا لخرائط مصدر الإعلان .
إذا قمت بتمكين --declarationMap ، فستتمكن من استخدام ميزات المحرر مثل "Go to Definition" وإعادة التسمية للتنقل بشفافية وتحرير التعليمات البرمجية عبر حدود المشروع في برامج التحرير المدعومة.

prepend مع outFile

يمكنك أيضًا تمكين الإعداد المسبق لمخرجات التبعية باستخدام الخيار prepend في المرجع:

   "references": [
       { "path": "../utils", "prepend": true }
   ]

سيشمل الإعداد المسبق للمشروع ناتج المشروع أعلى من ناتج المشروع الحالي.
يعمل هذا مع ملفات .js وملفات .d.ts ، كما سيتم إرسال ملفات خريطة المصدر بشكل صحيح.

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

  ^ ^ 
 /   \
B     C
 ^   ^
  \ /
   D

من المهم في هذا الموقف عدم الاعتماد مسبقًا على كل مرجع ، لأنك ستنتهي بنسختين من A بإخراج D - قد يؤدي هذا إلى نتائج غير متوقعة.

محاذير لمراجع المشروع

تحتوي مراجع المشروع على بعض المفاضلات التي يجب أن تكون على دراية بها.

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

بالإضافة إلى ذلك، للحفاظ على التوافق مع سير العمل البناء الحالية، tsc لن تبني تبعيات ما لم يحتج مع تلقائيا --build التبديل.
دعنا نتعلم المزيد عن --build .

وضع البناء لـ TypeScript

الميزة التي طال انتظارها هي عمليات الإنشاء الإضافية الذكية لمشاريع TypeScript.
في 3.0 يمكنك استخدام العلم --build مع tsc .
هذه نقطة دخول جديدة لـ tsc تتصرف كمنظم بناء أكثر من كونها مُترجمًا بسيطًا.

تشغيل tsc --build ( tsc -b للاختصار) سيؤدي إلى ما يلي:

  • البحث عن جميع المشاريع المشار إليها
  • اكتشف ما إذا كانت محدثة
  • إنشاء مشاريع قديمة بالترتيب الصحيح

يمكنك تزويد tsc -b بمسارات ملفات تكوين متعددة (مثل tsc -b src test ).
تمامًا مثل tsc -p ، فإن تحديد اسم ملف التكوين نفسه غير ضروري إذا كان اسمه tsconfig.json .

سطر الأوامر tsc -b

يمكنك تحديد أي عدد من ملفات التكوين:

 > tsc -b                                # Build the tsconfig.json in the current directory
 > tsc -b src                            # Build src/tsconfig.json
 > tsc -b foo/release.tsconfig.json bar  # Build foo/release.tsconfig.json and bar/tsconfig.json

لا تقلق بشأن طلب الملفات التي تمررها على سطر الأوامر - tsc سيعيد ترتيبها إذا لزم الأمر بحيث يتم دائمًا بناء التبعيات أولاً.

هناك أيضًا بعض العلامات الخاصة بـ tsc -b :

  • --verbose : طباعة التسجيل المطول لشرح ما يحدث (يمكن دمجه مع أي علم آخر)
  • --dry : يعرض ما يمكن فعله ولكن لا يقوم ببناء أي شيء فعليًا
  • --clean : حذف مخرجات المشاريع المحددة (يمكن دمجها مع --dry )
  • --force : تصرف كما لو أن جميع المشاريع قديمة
  • --watch : وضع المشاهدة (لا يجوز دمجه مع أي علم باستثناء --verbose )

تحفظات

عادة ، سينتج tsc مخرجات ( .js و .d.ts ) في وجود أخطاء بناء الجملة أو الكتابة ، ما لم يكن noEmitOnError قيد التشغيل.
سيكون القيام بذلك في نظام بناء تزايدي أمرًا سيئًا للغاية - إذا كان هناك خطأ جديد في إحدى التبعيات القديمة ، فستراه مرة واحدة فقط لأن الإنشاء اللاحق سيتخطى إنشاء المشروع المحدث الآن.
لهذا السبب ، يعمل tsc -b بفعالية كما لو أن noEmitOnError ممكّن لجميع المشاريع.

إذا قمت بإيداع أي مخرجات بناء ( .js ، .d.ts ، .d.ts.map ، إلخ.) ، فقد تحتاج إلى تشغيل بناء --force بعد بعض التحكم بالمصادر اعتمادًا على ما إذا كانت أداة التحكم بالمصدر تحافظ على خرائط الوقت بين النسخة المحلية والنسخة البعيدة.

msbuild

إذا كان لديك مشروع msbuild ، فيمكنك تشغيل تمكين وضع البناء عن طريق إضافة

    <TypeScriptBuildMode>true</TypeScriptBuildMode>

إلى ملف المشروع الخاص بك. سيؤدي ذلك إلى تمكين البناء الإضافي التلقائي بالإضافة إلى التنظيف.

لاحظ أنه كما هو الحال مع tsconfig.json / -p ، لن يتم احترام خصائص مشروع TypeScript الحالية - يجب إدارة جميع الإعدادات باستخدام ملف tsconfig الخاص بك.

قامت بعض الفرق بإعداد مهام سير عمل تستند إلى msbuild حيث يكون لملفات tsconfig نفس ترتيب الرسم البياني الضمني مثل المشاريع المُدارة التي يتم إقرانها بها.
إذا كان الحل الخاص بك على هذا النحو ، فيمكنك الاستمرار في استخدام msbuild مع tsc -p مع مراجع المشروع ؛ هذه قابلة للتشغيل المتبادل بشكل كامل.

إرشاد

الهيكل العام

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

من الممارسات الجيدة الأخرى أن يكون لديك ملف "حل" tsconfig.json يحتوي ببساطة على references لجميع مشاريع عقد الأوراق الخاصة بك.
هذا يمثل نقطة دخول بسيطة ؛ على سبيل المثال ، في TypeScript repo ، نقوم ببساطة بتشغيل tsc -b src لبناء جميع نقاط النهاية لأننا ندرج جميع المشاريع الفرعية في src/tsconfig.json
لاحظ أنه بدءًا من 3.0 ، لم يعد من الخطأ أن يكون لديك مصفوفة فارغة files إذا كان لديك على الأقل reference في ملف tsconfig.json .

يمكنك رؤية هذه الأنماط في مستودعات TypeScript - راجع src/tsconfig_base.json ، src/tsconfig.json ، و src/tsc/tsconfig.json كأمثلة رئيسية.

الهيكلة للوحدات النمطية النسبية

بشكل عام ، ليست هناك حاجة إلى الكثير لنقل الريبو باستخدام الوحدات النمطية النسبية.
ما عليك سوى وضع ملف tsconfig.json في كل دليل فرعي لمجلد رئيسي معين ، وإضافة reference s إلى ملفات التكوين هذه لمطابقة الطبقات المقصودة من البرنامج.
ستحتاج إما إلى تعيين outDir إلى مجلد فرعي واضح لمجلد الإخراج ، أو تعيين rootDir إلى الجذر المشترك لجميع مجلدات المشروع.

الهيكلة للملفات الخارجية

تخطيط التجميعات باستخدام outFile أكثر مرونة لأن المسارات النسبية لا تهم كثيرًا.
شيء واحد يجب أخذه في الاعتبار هو أنك تريد عمومًا عدم استخدام prepend حتى المشروع "الأخير" - سيؤدي ذلك إلى تحسين أوقات الإنشاء وتقليل مقدار الإدخال / الإخراج المطلوب في أي بنية معينة.
يعد مستودع TypeScript في حد ذاته مرجعًا جيدًا هنا - لدينا بعض مشروعات "المكتبات" وبعض مشروعات "نقطة النهاية" ؛ يتم الاحتفاظ بمشاريع "نقطة النهاية" صغيرة قدر الإمكان وتسحب فقط المكتبات التي يحتاجون إليها.

هيكلة monorepos

المهام: جرب أكثر واكتشف ذلك. يبدو أن لدى Rush و Lerna نماذج مختلفة تشير إلى أشياء مختلفة من جانبنا

ال 147 كومينتر

يا إلهي!

: +1:

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

جوناثان ،

شكرًا جزيلاً على ردود الفعل الطيبة وعلى اتخاذ هذا القرار. تعد TypeScript أداة رائعة وستساعد هذه الوظيفة العديد من الأشخاص الذين يرغبون في تكوين قواعد التعليمات البرمجية متوسطة الحجم الخاصة بهم والتي لا يمكن أن تبرر عدم الكفاءة التي تفرضها المشاريع الضخمة التي تعتمد على التقسيم الصارم للمخاوف (على سبيل المثال بوابات Azure أو مشروع Monacos of العالم مع> 100kloc والعديد من الفرق المستقلة). بعبارة أخرى ، سيساعد هذا حقًا "الأشخاص العاديين". أيضًا ، اقترح آخرون بالفعل أشياء لهذا ، على سبيل المثال NoelAbrahams (# 2180) ، وآخرين لذلك لا يمكنني المطالبة بالأصالة هنا. هذا مجرد شيء كنت أحتاجه منذ فترة.

أعتقد أن اقتراحك ممتاز. العيب الوحيد الذي أراه مقابل اقتراحي (# 3394) ، والذي أغلقته الآن ، هو عدم وجود آلية احتياطية للمراجع.

ضع في اعتبارك سيناريو العالم الحقيقي التالي الذي ذكرته بالتفصيل هنا: https://github.com/Microsoft/TypeScript/issues/3394#issuecomment -109359701

لديّ مشروع grunt-ts من TypeScript يعتمد على مشروع مختلف csproj2ts. لا يكاد أي شخص يعمل في grunt-ts سيرغب أيضًا في العمل على csproj2ts نظرًا لأنه يحتوي على نطاق وظائف محدود للغاية. ومع ذلك ، بالنسبة لشخص مثلي - سيكون من الرائع أن تكون قادرًا على العمل في كلا المشروعين في وقت واحد والقيام بإعادة البناء / الانتقال إلى التعريف / العثور على جميع المراجع عبرهما.

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

"dependencies": {
   "csproj2ts": ["../csproj2ts","node_modules/csproj2ts/csproj2ts.d.ts"],
   "SomeRequiredLibrary": "../SomeRequiredLibraryWithNoFallback"
}

لتبسيطها لتصبح مصفوفة ، أقترح التنفيذ البديل التالي لقسم افتراضي مستقبلي dependencies من ملف grunt-ts tsconfig.json :

"dependencies": [
   ["../csproj2ts","node_modules/csproj2ts/csproj2ts.d.ts"],
   "../SomeRequiredLibraryWithNoFallback"
]

ستكون قاعدة الدقة لكل عنصر من عناصر المصفوفة في dependencies : العنصر _first_ الموجود في كل عنصر هو العنصر المستخدم ، ويتم تجاهل الباقي. يتم التعامل مع العناصر من نوع السلسلة تمامًا كما ينص اقتراح جوناثان.

هذا حل أكثر تعقيدًا إلى حد ما من حيث التنفيذ ، ولكنه يمنح المطور (ومؤلفي المكتبة) مرونة أكبر. بالنسبة للمطورين الذين لا يحتاجون إلى التطوير على csproj2ts (وبالتالي ليس لديهم ملف ../csproj2ts/tsconfig.json ) ، ستكون التبعية مجرد ملف تعريف يتم إضافته إلى سياق الترجمة. بالنسبة للمطورين الذين لديهم _do_ ملف ../csproj2ts/tsconfig.json ، سيعمل الاقتراح تمامًا كما وصفته أعلاه.

في المثال أعلاه ، يجب أن يكون "../SomeRequiredLibraryWithNoFallback" موجودًا تمامًا كما هو الحال في اقتراحك الحالي ، وسيكون غيابه خطأ في المترجم.

شكرا جزيلا لك على النظر في هذا.

هناك مشكلتان هنا نحتاج إلى تفكيكهما ، هناك بناء ، وهناك دعم لخدمة اللغة.

بالنسبة إلى Build ، لا أعتقد أن tsconfig هو المكان المناسب لذلك. من الواضح أن هذه مشكلة في نظام البناء. مع هذا الاقتراح ، يجب أن يكون المترجم المطبوع عليه في الأعمال التجارية التالية:

  • معرفة التبعية
  • الشيكات المحدثة جيئة وذهابا من التأكيدات
  • إدارة التكوين (الإصدار مقابل التصحيح)

من الواضح أن هذه كلها مسؤولية بناء الأنظمة ؛ هذه مشكلات صعبة وهناك بالفعل أدوات تقوم بذلك ، مثل MSBuild و grunt و gulp وما إلى ذلك.
بمجرد أن يصبح tsconfig و tsc محرك الإنشاء ، قد ترغب في استخدام جميع وحدات المعالجة المركزية لإنشاء أشجار فرعية غير ذات صلة ، أو الحصول على أوامر النشر والمسبقة لكل مشروع ، وربما إنشاء مشاريع أخرى أيضًا. مرة أخرى ، أعتقد أن هناك أدوات بناء جيدة في ما يفعلونه ، ولا داعي لإعادة إنشاء ذلك.

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

"files" : [
    "file1.ts",
    {
        "path": "../projectB/out/projectB.d.ts",
         "sourceProject": "../projectB/"
     }
]

حيث ستنظر tsc فقط في "المسار" ولكن يمكن للأدوات أن تبحث في المعلومات الأخرى وتحاول أن تكون مفيدة قدر الإمكان.

أقر بوجود المشكلة ولكن لا أعتقد أن البناء الجماعي والأدوات هو الحل الصحيح. يجب أن يظل tsconfig.json حقيبة تكوين (أي بديل json لملفات الاستجابة) وألا يصبح نظامًا للبناء. يمثل tsconfig.json واحد استدعاء tsc واحدًا. يجب أن يظل tsc كمترجم مشروع واحد.

تعد مشاريع MSBuild في VS مثالًا على استخدام نظام إنشاء لإنشاء ميزات IDE والآن لا تشعر شركة ppl بالرضا عنها لأنها كبيرة جدًا.

شكرا على ردك يا ​​محمد. اسمحوا لي أن أكرر لمعرفة ما إذا كنت أفهم:

  • تعتقد أن مهمة تنسيق عمليات إنشاء المشاريع المتعددة يجب أن تظل مجال أدوات البناء المخصصة.
  • تعتقد أنه قد يكون هناك شيء ما لهذا الاقتراح لخدمة لغة TypeScript.
  • تعتقد أن تشغيل tsc --project على هذا tsconfig.json سيكون مثل تشغيل tsc file1.ts ../project/out/project.d.ts . ومع ذلك ، فإن فتح مثل هذا المشروع في VS أو محرر آخر مع خدمة لغة TypeScript سيسمح "بالانتقال إلى التعريف" لإحضار المطور إلى ملف TypeScript الفعلي _ حيث تم تعريف الميزة (بدلاً من التعريف في projectB.d.ts )

هل لدي هذا الحق؟

إذا كان الأمر كذلك ، أعتقد أن هذا عادل جدًا. في اقتراحي الأصلي (https://github.com/Microsoft/TypeScript/issues/3394) ، قلت إن فكرتي كانت غير مكتملة لأنها لم تتضمن خطوة نسخ النتائج المنبعثة من مكان إخراجها في المكتبة المرجعية إلى المكان الذي تتوقعه مكتبة المراجع في وقت التشغيل. أعتقد أنك تقول "لماذا تذهب في منتصف الطريق للبناء بينما ما هو مطلوب حقًا هو دعم خدمة اللغة".

لتغيير البيانات قليلاً في مثالك ، هل ترغب في دعم شيء كهذا؟

"files" : [
    "file1.ts",
    {
        "path": "externalLibraries/projectB.d.ts",
         "sourceProject": "../projectB/"
     }
]

الافتراض هو أن المشروع الحالي سيأتي مع تعريف للمشروع ب يتم استخدامه بشكل افتراضي ، ولكن إذا كان المصدر الفعلي للمشروع ب متاحًا ، فسيتم استخدام المصدر الفعلي بدلاً من ذلك.

nycdotnet لقد

يبدو عظيما!

أتفق مع mhegazy وفي الواقع أعتقد أنه من المهم بالنسبة لـ TypeScript التوقف عن التفكير في نفسها كـ "مترجم" والبدء في التفكير في نفسها على أنها "مدقق نوع" و "مترجم". يوجد الآن دعم للترجمة لملف واحد ولا أرى أي سبب لإنشاء ملفات جافا سكريبت المجمعة باستثناء وقت التشغيل / التجميع. لا أفهم أيضًا سبب ضرورة إنشاء تعريفات مرجعية خارجية أثناء فحص النوع عندما يكون المصدر الفعلي للطباعة متاحًا.

يعد حل الملفات والحزمة من مسؤولية نظام الإنشاء الذي تستخدمه (browserify و systemjs و webpack وما إلى ذلك) ، لذلك لكي تعمل الأدوات ، يجب أن تكون خدمة اللغة قادرة على حل الملفات بنفس الطريقة مثل أي نظام بناء / نظام أساسي تستخدمه يستخدمون. هذا يعني إما تنفيذ LanguageServicesHost مخصصة لكل نظام بناء أو توفير أداة لكل منها تقوم بإنشاء إدخالات التعيين الصحيحة في tsconfig.json. أي منهما مقبول.

nycdotnet أعتقد أنه من الأفضل التعامل مع حالة الاستخدام الخاصة بك للعديد من المسارات الاحتياطية باستخدام npm link ../csproj2ts ؟

أتفق مع mhegazy على أننا يجب أن نبقي البناء منفصلاً عن المترجم / المترجم. أود تضمين تبعية tsconfig -> tsconfig في قسم الملفات على افتراض أنه إذا لم يسرد القسم أي ملفات * .ts ، فإنه لا يزال يبحث عنها. على سبيل المثال

"الملفات": [
{
"المسار": "externalLibraries / projectB.d.ts"،
"sourceProject": "../projectB/"
}
]

سيستمر تضمين جميع ملفات ts في الدليل والدليل الفرعي الذي يحتوي على ملف tsconfig.json.

dbaeumer ثم تريد الحصول عليها في خاصية مختلفة ، أليس كذلك؟ حاليًا ، إذا تم تعريف الملفات ، فسيتم استخدامها دائمًا ونتجاهل جزء include * .ts.

mhegazy ليس بالضرورة قسمًا مختلفًا على الرغم من أنه سيجعل الأمور أكثر وضوحًا في النهاية. كل ما أريد تجنبه هو إجباري على سرد كافة الملفات إذا استخدمت tsconfig -> تبعيات tsconfig. في المثال أعلاه ، ما زلت أرغب في عدم سرد أي ملفات * .ts لإدخالها في المترجم.

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

في الاقتراح أعلاه (حيث تتم الإشارة إلى كل من .d.ts والمصدر) ، هل يكتشف ما إذا كان ملف .d.ts قديمًا (أي يحتاج إلى إعادة بنائه)؟ هل تعمل عمليات مثل Refactor / Rename عبر المشاريع (على سبيل المثال ، تحديث الاسم في مصدر المشروع المشار إليه ، وليس فقط ملف .d.ts الذي سيتم استبداله بالبنية التالية)؟ هل يأخذني GoToDef إلى الكود الأصلي في المشروع المشار إليه (وليس منتصف ملف d.ts العملاق للمشروع بأكمله)؟ قد يبدو هذا يعني الحاجة إلى حل ، وفي بعض الحالات تحليل ، مصدر المشاريع المشار إليها ، وفي هذه الحالة هل ملفات .d.ts مفيدة؟

الحل العام ، الذي لدينا اليوم ، لديك .d.ts كمخرج بناء لمشروع واحد ، ثم تتم الإشارة إليه كمدخل في مشروع آخر. هذا يعمل بشكل جيد للبناء ، لذلك لا حاجة لتغيير ذلك.

المشكلة هي سيناريو التحرير. لا تريد المرور عبر ملف تم إنشاؤه أثناء التحرير. الحل الذي أقترحه هو تقديم "تلميح" عن مصدر ملف .d.ts الذي تم إنشاؤه. لن تقوم خدمة اللغة بعد ذلك بتحميل ملف .d.ts ، وبدلاً من ذلك تقوم بتحميل "مشروع" من مسار التلميح. بهذه الطريقة ، ستأخذك goto def إلى ملف التنفيذ بدلاً من .d.ts وستعمل الأخطاء المماثلة دون الحاجة إلى تجميع.

عمليات مثل إعادة التسمية ، سوف "تنتشر" من مشروع إلى آخر ، وبالمثل تجد المراجع ، ستفعل.

اليوم ، الأمر متروك تمامًا للمضيف (IDE ، أيًا كان) للعثور على ملف tsconfig.json ، على الرغم من أن TS يوفر بعد ذلك واجهات برمجة التطبيقات لقراءته وتحليله. كيف يمكنك تصور هذا العمل إذا كان هناك العديد من tsconfig.json موجودة بطريقة هرمية؟ هل سيظل المضيف مسؤولاً عن حل الملف الأولي وليس الملفات الأخرى أم أن المضيف سيكون مسؤولاً عن حل جميع ملفات tsconfigs؟

يبدو أن هناك مفاضلة بين الراحة / الاتفاقية والمرونة.

ألن يبدأ هذا بالقدرة على إنشاء ملفات d.ts كما هو موضح في # 2568 (أو على الأقل الحصول على واردات نسبية)؟

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

mhegazy عفوا ، آسف. بالنظر إلى المشكلة مرة أخرى ، يبدو أن هذا أكثر ارتباطًا بخدمة اللغة. قرأت ما يلي

  • المشاريع متوسطة الحجم: تلك التي تحتوي على بنى قياسية ومكونات مشتركة

وافترضت تلقائيًا أنها مرتبطة بدعم أفضل لـ npm / browserify (أو webpack) لبناء worfklows حيث تكون أجزاء من المشروع وحدات خارجية.

AFAIK لا توجد طريقة لإنشاء ملف (ملفات) d.ts للوحدات الخارجية حتى الآن؟ إذا كان الأمر كذلك ، فإن الطريقة الوحيدة التي يمكن لخدمة اللغة من خلالها ربط المشاريع التي تستورد وحدات خارجية هي الحصول على شيء مثل هذا في tsconfig.json:

{ 
  "provides": "external-module-name"
}

والتي من شأنها إعلام LS عندما تتم الإشارة إلى المشاريع في tsconfig.json

AFAIK لا توجد طريقة لإنشاء ملف (ملفات) d.ts للوحدات الخارجية حتى الآن؟

لا أعتقد أن هذا صحيح. سيؤدي استدعاء tsc --m --d إلى إنشاء ملف إعلان يمثل وحدة نمطية خارجية بحد ذاتها. سيحاول منطق الدقة العثور على ملف .ts وإذا لم يكن كذلك ، فسيحاول منطق الدقة العثور على .d.ts بنفس الاسم ،

يمكن لـ spion TypeScript إنشاء ملفات d.ts للوحدات الخارجية كما قال mhegazy ، ولكن هذا ينتج عنه نسبة 1: 1 من التعريفات لملفات المصدر والتي تختلف عن كيفية استهلاك تعريفات TypeScript للمكتبة. إحدى الطرق للتغلب على هذا هي مكتبة TypeStrong: https://github.com/TypeStrong/dts-bundle

mhegazy آسف ، قصدت "الوحدات الخارجية المحيطة" ، أي إذا كتبت external-module-name في TypeScript وقمت باستيراد أحد فئاته من وحدة نمطية أخرى:

import {MyClass} from 'external-module-name'

لا توجد طريقة لجعل tsc ينشئ ملف .d.ts المناسب الذي يصرح عن 'external-module-name'

nycdotnet أنا على دراية بحزمة dts و

ما هي حالة هذه الميزة؟ يبدو أن هذا خيار مهم للمشاريع المتوسطة الحجم. كيف يمكنك تكوين مشروع له مصدر في مجلدات مختلفة بتكوين "يتطلب js" محدد؟

llgcode ، يرجى إلقاء نظرة على https://github.com/Microsoft/TypeScript/issues/5039 ، يجب أن يكون هذا متاحًا في typescript@next .

لا أفهم حقًا ما هو صعب للغاية بشأن كتابة ملف gulpfile مع المهام التي تجمع المشاريع الفرعية بالطريقة التي تحتاجها للمشروعات متوسطة الحجم. حتى أنني أفعل ذلك في مشاريع صغيرة الحجم. السبب الوحيد لاستخدام tsconfig.json على الإطلاق هو VS Code

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

llgcode حسنًا ، مهام . تكتب gulpfile.js حيث تحدد العديد من المهام كما تريد باستخدام gulp.task() . داخل مهمتك ، يمكنك أن تأخذ دفقًا من ملفات الإدخال مع gulp.src() ثم .pipe() منهم من خلال خط أنابيب من التحويلات ، مثل التجميع والتسلسل والتصغير وخرائط المصادر ونسخ الأصول ... يمكنك افعل أي شيء ممكن باستخدام وحدات Node و NPM.
إذا كان يجب عليك تجميع مشاريع متعددة ، فما عليك سوى تحديد مهمة تقوم بذلك. إذا كنت ترغب في استخدام tsconfig.json متعددة ، فإن gulp -typescript يدعم ذلك ، أو يمكنك فقط قراءة ملفات json. التراكيب الإضافية ممكنة أيضًا. لا أعرف كيف يتم تنظيم مشروعك ، إذا كان لديك في مستودعات مختلفة وتستخدم وحدات فرعية ، أو أيًا كان. لكن البلع مرن بنسبة 100٪.

حسنًا ، يبدو أن الشكر أداة رائعة. إذا كنت أطلب تعيينًا مثل يتطلب ("mylibs / lib") وكانت ملفاتي موجودة على سبيل المثال في مشروع مجلد / src / lib.js ، فلن يعمل الإكمال في atom ولا أعرف كيف سيتم حل الحروف المطبوعة أو gulp تم التعيين / التكوين باستخدام "mylibs" والمسار المحلي. لذلك أعتقد أن مسارات الخيارات الجديدة هذه في # 5039 تعد حلاً جيدًا لهذه المشكلة.

llgcode حسنًا باستخدام https://www.npmjs.com/package/gulp-typescript#resolving -files.

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

felixfbecker لا أوافق. كل مترجم (مع فحص النوع) أعرفه لديه خيار مثل هذا. على سبيل المثال:
مجلس التعاون الخليجي -> تضمين الملفات
جافا -> classpath & sourcepath
اذهب -> جوباث
بيثون -> بايثونباث
يحتاج المحول البرمجي / المترجم إلى معرفة الملفات المصدر التي تحتاج إلى نقل ما هي ملفات المصدر التي تتضمن ملفات / lib فقط.
هناك حاجة إلى أداة إنشاء مثل gulp لمعرفة ما يجب فعله عند تغيير الملف.

أوافق wtihllgcode . أيضًا ، إلى جانب التعريض كمترجم ، تعرض TypeScript أيضًا كخدمة لغة ، والتي توفر تمييز بناء الجملة (الاكتشاف الفعلي) ووظيفة الإكمال لـ IDE. وتحتاج أيضًا إلى السير في شجرة التبعية.

llgcode نقاط صالحunional. أحد الأشياء التي قد تساعد أيضًا هو جعل الخاصية files في tsconfig.json تقبل globs حتى تتمكن من تحديد جميع الملفات في جميع المجلدات التي تريد تضمينها. لكني أرى من أين أتيت ولماذا قد يرغب المرء في عدة tsconfig.json لمشاريع أكبر.

AFAIK لـ CommonJS هذا مدعوم بالفعل عبر node_modules و npm link ../path/to/other-project

لا يعمل ارتباط npm بمجرد أن تبدأ في إعادة استخدام المكتبات عبر المشاريع. إذا كنت تستخدم مكتبة مشتركة بين مشروعين منفصلين خاصين بك ، (مع أخذ rxjs كمثال) ستخبرك الكتابة المطبوعة أن "Observable لا يمكن تعيينه إلى Observable". ذلك لأن مسارات التضمين تتبع مجلدات الروابط الرمزية لمجلدين مختلفين من وحدات node_modules وعلى الرغم من كونها نفس المكتبة. تؤدي الحلول البديلة إلى إنشاء مهام gulp أو عمليات إعادة الشراء المحلية / الخاصة npm ، وتعود بشكل أساسي إلى خيار المشروع الكبير.

EricABC thats ربما لأنهم يستخدمون إقرارات الوحدة الخارجية المحيطة ، وفي هذه الحالة يجب عليهم أيضًا تضمين تعريفات لملفات node_modules القائمة على d.ts. بخلاف ذلك ، لا ينبغي أن تكون هناك مشكلة لأن أنواع TS يتم فحصها هيكليًا فقط ، لذلك لا يهم ما إذا كانت تأتي من وحدات مختلفة أو لها أسماء مختلفة طالما تتطابق الهياكل.

شكرًا spion ، افترضت للتو أنها كانت قائمة على الملفات ، يبدو

الشيء الوحيد الذي قد يساعد أيضًا هو جعل خاصية الملفات في tsconfig.json تقبل globs ...

هناك خاصية include قيد المناقشة

أسئلة وملاحظات:

  • يجب أن يسمح dependencies بمسار tsconfig.json الكامل لأن tsc يسمح بذلك
  • لماذا نقدم كلمة رئيسية جديدة ( dependencies ) بينما files موجودة بالفعل وهي جيدة؟
    مثال:
{
    "compilerOptions": {
        // ...
    },
    "files": [
        "../common/tsconfig.json", // <== takes the `files` part of the tsconfig.json
        "../common/tsconfig.util.json", // <==
        "core.ts",
        "sys.ts"
    ]
}
  • ماذا يحدث إذا حددت التبعية tsconfig.json أيضًا compilerOptions ؟


لنذهب أبعد من ذلك / wild :-) وربما نسمح (في المستقبل) compilerOptions ، exclude ... للإشارة إلى tsconfig.json آخر:

// File app/tsconfig.json
{
    "compilerOptions": "../common/tsconfig.compilerOptions.json",
    "files": [
        "../common/tsconfig.json",
        "../common/tsconfig.util.json",
        "core.ts",
        "sys.ts"
    ],
    "exclude": "../common/exclude.json"
}

// File ../common/tsconfig.compilerOptions.json
{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true
    }
}

// File ../common/exclude.json
{
    "exclude": [
        "node_modules",
        "wwwroot"
    ]
}

// File ../common/tsconfig.util.json
{
    "files": [
        "foo.ts",
        "bar.ts"
    ]
}

لقد حصلت على المنطق: files ، compilerOptions ، exclude ... يمكنه الرجوع إلى ملفات tsconfig.json الأخرى وسيأخذ فقط جزء الكلمة الأساسية المطابق من tsconfig الآخر ملف .json => سهل وقابل للتحجيم. يمكنك بالتالي تقسيم tsconfig.json إلى ملفات متعددة إذا أردت وإعادة استخدامها.

عند قراءة جزء من مناقشتك ، فإن الأمر الأكثر صلة هو الحصول على "خدمة اللغة" / تعريف تعريف الانتقال بشكل صحيح. تستخدم مصححات جافا سكريبت sourceMaps. الآن ، إذا قام tsc بإنشاء بيانات sourceMap ليس فقط في ملفات .js ولكن أيضًا في ملفات .d.ts ...

أبعد من ذلك ، لا أرى حقًا فائدة كبيرة في تشغيل إنشاءات المشاريع الفرعية من داخل ملف tsconfig.json. إذا كنت بحاجة إلى هذا النوع الأساسي من بناء تبعيات الوقت ، فإن برنامج نصي بسيط يقوم بهذه المهمة. إذا كنت بحاجة إلى بناء تدريجي ذكي ، من ناحية أخرى ، فإن النهج المقترح يبدو بسيطًا للغاية. في العديد من السيناريوهات ، ينتهي الأمر بـ tsc على أنه مجرد خطوة بناء واحدة من بين خطوات أخرى. كيف تبعيات كتابة غريبة لـ tsc في tsconfig.json ولكن بعض الملفات الأخرى لبقية ذلك؟ مرة أخرى ، بالنسبة للأشياء البسيطة مع كون tsc هو خطوة البناء الوحيدة التي سيفعلها برنامج shell script.

على أي حال ، ماذا عن إنشاء تعيين المصدر في ملفات .d.ts تمامًا كما في ملفات .js؟

نحن ببساطة نستخدم وحدات العقدة + رابط npm ، الشيء الوحيد الذي لا يعمل هو أن الوحدة النمطية: العقدة غير متوافقة مع وحدات ES6 ، والتي تتيح تحسينات التضمين / اهتزاز الشجرة (انظر أيضًا # 11103)

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

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

لذا ، مهما كان هذا الأمر ، أتمنى أن أتمكن أخيرًا من الحصول على حل أنيق لتجربة التطوير بأكملها.

مجرد رنين في أن هذا سيكون رائعًا لعملنا اليومي!

نظرًا لطبيعة تطوير الويب ، لدينا عدة مشروعات ts مع كل مشروع يحتوي على عدة ملفات ts مجمعة في ملف js واحد ( --outFile ). هذه إما مشاريع شبيهة بالتطبيقات (تقوم بشيء معين أو تضيف ميزة معينة) أو مشاريع تشبه lib (رمز قابل لإعادة الاستخدام للتطبيقات). غالبًا ما نعمل على العديد من مشاريع ts في نفس الوقت ، مما يعزز المكتبات لتسهيل التطوير على التطبيقات. لكنني لا أعتقد أن أيًا من زملائي المطورين لديهم جميع مشاريعنا في بيئاتهم المحلية في أي وقت أيضًا.

لتحسين سير العمل لدينا ، فإن خياراتنا الحالية هي

  • رمي كل شيء في مشروع 1 ts

    • يمكننا الرجوع إلى ملفات .ts مباشرة ، وهو أجمل بكثير من استخدام ملفات d.ts

    • لكننا نحتاج إلى أداة خارجية لتعيين مجموعات من الملفات وتسلسلها ، نظرًا لأننا نحتاج إلى تقييد ملفات js المطلوبة عبر interwebs مع الحفاظ على نمطية التطبيقات (التي تكون خاصة بميزة أو صفحة).

    • كما ذكرنا ، ليست كل مشاريع ts هذه مطلوبة في جميع الأوقات للجميع ، لذا فإن هذا من شأنه أن يضيف الكثير من الانتفاخ إلى نظام الملفات. قد يحتاج شخص ما يعمل في المشروع X إلى المشاريع A و B و D ولكن قد يحتاج شخص يعمل على Y إلى A و C.

  • إبقاء المشاريع منفصلة (وضعنا الحالي)

    • نحتاج إلى الإشارة إلى ملفات d.ts المترجمة من مشاريع ts الأخرى لأن تضمين ملف .ts مباشرة سيضيفه إلى الإخراج. سيكون الأمر أسرع كثيرًا إذا تمكنا من إدخال f12 مباشرة في الكود المصدري الخاص بنا.

    • ونحتاج إلى إضافة أدوات / نصوص لتجميع العديد من هذه المشاريع في نفس الوقت. حاليًا إما نبدأ أوامر tsc -d -w من محطات طرفية متعددة ، أو نشغل برنامج نصي يقوم بذلك لجميع الأدلة الفرعية حيث يوجد tsconfig.

    • أفهم أن الأدوات الأخرى يمكن أن تساعد في هذا (مثل gulp) أو ربما يمكننا اكتشاف شيء ما باستخدام ملف globs في tsconfigs ، ولكن هذا لن يساعد في الإصدار الأول من ملفات d.ts.

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

إذا كان dependencies هو الخيار الأفضل لكلا العالمين ، فسيكون ذلك مذهلاً ؛ وظائفالعلامات لجميع ملفات ts الخاصة بالتبعية ، ولكن قم بتجميع المخرجات وفقًا لـ tsconfig الخاص بتلك التبعية.

هل هناك أي تحديث لهذا الموضوع. كيف يمكننا الحصول على العديد من مشاريع الكتابة المطبوعة التي تجمع بعضها البعض بشكل مستقل ؟ كيف يمكننا وصف مثل هذه التبعية في tsconfig.json؟

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

هل هناك أي تحديث لهذا الموضوع. كيف يمكننا الحصول على العديد من مشاريع الكتابة المطبوعة التي تجمع بعضها البعض بشكل مستقل؟ كيف يمكننا وصف مثل هذه التبعية في tsconfig.json؟

يجب أن يتم ترميز تبعية البناء في نظام البناء الخاص بك. بناء أنظمة مثل البلع ، النخر ، القرنبيط ، msbuild ، القاعدية ، إلخ .. مصممة للتعامل مع مثل هذه الحالات.
بالنسبة لمعلومات النوع ، يجب أن يتضمن ناتج أحد المشاريع a .d.ts ويجب أن يتم تمريره كمدخل إلى الآخر.

mhegazy يعمل مشروعنا على هذا "types" في tsconfig.json . يتم تصنيف كل مشروع مع --outFile (هو مشروع القديمة التي لم تتحرك إلى وحدات ES بعد)، و "typings" package.json النقاط الرئيسية لالمجمعة .d.ts ملف.

نستخدم البلع للتجميع / المشاهدة.

إنه يعمل في الغالب ، ولكن هناك بعض المشكلات:

  • نظرًا لوجود مشكلات مثل # 15488 و # 15487 ، نحتاج إلى ارتباط واضح حتى تعمل المراجع بشكل صحيح.
  • سينقلك Go-to-definition إلى ملف مجمّع .d.ts . من الناحية المثالية ، سينقلك هذا إلى المصدر في مشروع آخر.
  • أسرع طريقة للقيام ببنية كاملة هي lerna run build --sort (فعليًا tsc في كل دليل) ، والتي لها عبء إضافي لأنها ستنتج عملية مترجم TypeScript واحدة لكل حزمة ، مما يؤدي إلى الكثير من العمل المتكرر .

إنني أراقب هذه المشكلة عن كثب لأننا أيضًا في نفس الموقف الذي وصفه الآخرون.
"مشاريع" متعددة ، كل منها بملفها tsconfig.json.

لدينا عملية البناء التي تعمل مثل mhegazy المشار إليها: كل مشروع يصدر ملف .d.ts ويستخدم كمدخل للمشاريع المعتمدة.

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

It's happening

يا إلهي

سيناريو محدث أود أن يكون فيه هذا يتضمن مكونات React. لدينا مستودع مكونات يحتوي على وحدات JSX (الذرات والجزيئات والكائنات الحية) التي تجعل مكونات واجهة المستخدم مناسبة لجميع التطبيقات في شركتنا. يتم استخدام ريبو المكونات هذا من قبل جميع مطوري الواجهة الأمامية أثناء عملهم على تطبيقاتهم الفردية. سيكون من الجيد جدًا أن يكون لديّ تجربة خدمة لغة TypeScript تسمح لي بتحرير واجهة المستخدم للتطبيق المحدد و "الانتقال إلى التعريف" في مستودع مكونات واجهة المستخدم الشائعة. اليوم يتعين علينا تجميع هذه المكونات بشكل فردي ونسخها. هذه هي مشكلة "اصنع مشروعك الخاص بالسباكة" التي أود أن أراها ثابتة (والتي توجد لها قصة جميلة جدًا في عالم .NET مع وجود مشاريع تحت الحل).

مراجع المشروع: قابلية التوسع المضمنة لـ TypeScript

مقدمة

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

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

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

سنحدد القيود الرئيسية التي يفرضها هذا النظام ونضع إرشادات لتحديد حجم المشروع وهيكل الدليل وأنماط البناء.

سيناريوهات

هناك ثلاثة سيناريوهات رئيسية يجب مراعاتها.

الوحدات النسبية

تستخدم بعض المشاريع على نطاق واسع الواردات النسبية . يتم حل هذه الواردات بشكل لا لبس فيه إلى ملف آخر على القرص. قد يكون من الشائع العثور على مسارات مثل ../../core/utils/otherMod ، على الرغم من تفضيل بنى الدليل المسطحة عادةً في عمليات إعادة الشراء هذه.

مثال

هذا مثال من مشروع بيرسيوس التابع لأكاديمية خان:

مقتبس من https://github.com/Khan/perseus/blob/master/src/components/graph.jsx

const Util = require("../util.js");
const GraphUtils = require("../util/graph-utils.js");
const {interactiveSizes} = require("../styles/constants.js");
const SvgImage = require("../components/svg-image.jsx");

ملاحظات

بينما تشير بنية الدليل إلى بنية المشروع ، إلا أنها ليست بالضرورة نهائية. في نموذج Khan Academy أعلاه ، يمكن أن نستنتج أن util و styles و components المحتمل أن يكون مشروعهم الخاص. ولكن من الممكن أيضًا أن تكون هذه الأدلة صغيرة جدًا وسيتم تجميعها في وحدة بناء واحدة.

أحادي الريبو

يتكون الريبو الأحادي من عدد من الوحدات النمطية التي يتم استيرادها عبر مسارات غير نسبية . قد تكون الواردات من الوحدات الفرعية (مثل import * as C from 'core/thing ) شائعة. عادةً ، ولكن ليس دائمًا ، يتم نشر كل وحدة جذر بالفعل على NPM.

مثال

مقتبس من https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts

import {InjectionToken, ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core';
import {forkJoin} from 'rxjs/observable/forkJoin';
import {map} from 'rxjs/operator/map';
import {AbstractControl, FormControl} from './model';

ملاحظات

وحدة القسمة ليست بالضرورة الجزء الأول من اسم الوحدة. على سبيل المثال ، يقوم rxjs بتجميع الأجزاء الفرعية ( observable ، operator ) بشكل منفصل ، كما تفعل أي حزمة محددة النطاق (مثل @angular/core ).

ملف

يمكن لـ TypeScript دمج ملفات الإدخال الخاصة بها في ملف JavaScript منفرد. التوجيهات المرجعية ، أو ترتيب الملفات في tsconfig.json ، قم بإنشاء ترتيب إخراج حتمي للملف الناتج. نادرًا ما يستخدم هذا للمشاريع الجديدة ، لكنه لا يزال مألوفًا بين قواعد الكود القديمة (بما في ذلك TypeScript نفسها).

مثال

https://github.com/Microsoft/TypeScript/blob/master/src/compiler/tsc.ts

/// <reference path="program.ts"/>
/// <reference path="watch.ts"/>
/// <reference path="commandLineParser.ts"/>

https://github.com/Microsoft/TypeScript/blob/master/src/harness/unittests/customTransforms.ts

/// <reference path="..\..\compiler\emitter.ts" />
/// <reference path="..\harness.ts" />

ملاحظات

سيتم تحميل بعض الحلول التي تستخدم هذا التكوين كل outFile عبر علامة script منفصلة (أو ما يعادلها) ، لكن البعض الآخر (مثل TypeScript نفسها) تتطلب تسلسل الملفات السابقة لأنها تبني مخرجات متجانسة .

مراجع المشروع: وحدة عزل جديدة

بعض الملاحظات الحرجة من التفاعل مع المشاريع الحقيقية:

  • عادةً ما يكون TypeScript "سريعًا" (<5-10 ثوانٍ) عند التحقق من المشاريع التي تقل عن 50000 LOC من كود التنفيذ (غير .d.ts)
  • تعتبر ملفات .d.ts ، خاصةً التي تقل عن skipLibCheck ، "مجانية" تقريبًا من حيث فحص الكتابة وتكلفة الذاكرة
  • يمكن تقسيم جميع البرامج تقريبًا إلى مكونات أصغر من 50000 LOC
  • تفرض جميع المشاريع الكبيرة تقريبًا بالفعل بعض هيكلة ملفاتها حسب الدليل بطريقة تنتج مكونات فرعية متوسطة الحجم
  • تحدث معظم عمليات التحرير في مكونات العقدة الطرفية أو العقدة القريبة من العقدة التي لا تتطلب إعادة فحص أو إعادة إرسال الحل بأكمله

بتجميع هذه العناصر معًا ، إذا كان من الممكن فقط التحقق من كتابة 50000 LOC قطعة واحدة من كود التنفيذ في وقت واحد ، فلن تكون هناك تفاعلات "بطيئة" تقريبًا في سيناريو تفاعلي ، ولن تنفد الذاكرة أبدًا.

نقدم مفهومًا جديدًا ، مرجعًا للمشروع ، يعلن عن نوع جديد من التبعية بين وحدتي ترجمة TypeScript حيث لا يتم التحقق من كود تنفيذ الوحدة التابعة ؛ بدلاً من ذلك ، نقوم ببساطة بتحميل ناتجه .d.ts من موقع محدد.

بناء الجملة

تمت إضافة خيار references (TODO: Bikeshed!) إلى tsconfig.json :

{
  "extends": "../tsproject.json",
  "compilerOptions": {
    "outDir": "../bin",
    "references": [
      { "path": "../otherProject" }
    ]
  }
}

تحدد مصفوفة references مجموعة من المشاريع الأخرى للرجوع إليها من هذا المشروع.
يشير كل عنصر references path إلى ملف tsconfig.json أو مجلد يحتوي على ملف tsconfig.json .
يمكن إضافة خيارات أخرى لهذا الكائن عندما نكتشف احتياجاتهم.

دلالات

تغير مراجع المشروع السلوك التالي:

  • عندما يتم حل حل الوحدة النمطية إلى ملف .ts في دليل فرعي للمشروع rootDir ، فإنه يتحول بدلاً من .d.ts في هذا المشروع outDir

    • إذا فشل هذا الحل ، فيمكننا على الأرجح اكتشافه وإصدار خطأ أكثر ذكاءً ، على سبيل المثال Referenced project "../otherProject" is not built بدلاً من "ملف غير موجود" بسيط

  • لا شيء آخر (TODO: حتى الآن؟)

قيود أداء المشاريع المشار إليها

لتحسين أداء الإنشاء بشكل مفيد ، نحتاج إلى التأكد من تقييد سلوك TypeScript عندما يرى مرجعًا للمشروع.

على وجه التحديد ، يجب أن تكون الأشياء التالية صحيحة:

  • لا تقرأ
  • فقط tsconfig.json ينبغي أن يقرأ من مشروع المشار إليه من القرص
  • يجب ألا يتطلب الفحص الحديث انتهاك القيود المذكورة أعلاه

للوفاء بهذه الوعود ، نحتاج إلى فرض بعض القيود على المشاريع التي تشير إليها.

  • يتم ضبط declaration تلقائيًا على true . من الخطأ محاولة تجاوز هذا الإعداد
  • rootDir افتراضيًا هو "." (الدليل الذي يحتوي على ملف tsconfig.json ) ، بدلاً من الاستدلال عليه من مجموعة ملفات الإدخال
  • إذا تم توفير مصفوفة files ، فيجب أن توفر أسماء جميع ملفات الإدخال

    • استثناء: لا يلزم تحديد الملفات المضمنة كجزء من مراجع النوع (مثل تلك الموجودة في node_modules/@types )

  • يجب أن يحتوي أي مشروع تمت الإشارة إليه على مصفوفة references (والتي قد تكون فارغة).

لماذا "declaration": true ؟

تعمل مراجع المشروع على تحسين سرعة الإنشاء باستخدام ملفات التصريح (.d.ts) بدلاً من ملفات التنفيذ الخاصة بها (.ts).
لذلك ، بطبيعة الحال ، يجب أن يكون الإعداد declaration لأي مشروع مشار إليه.
هذا يعني من خلال "project": true

لماذا تغير rootDir ؟

يتحكم rootDir كيفية تعيين ملفات الإدخال لأسماء ملفات الإخراج. يتمثل السلوك الافتراضي لـ TypeScript في حساب دليل المصدر الشائع للرسم البياني الكامل لملفات الإدخال. على سبيل المثال ، مجموعة ملفات الإدخال ["src/a.ts", "src/b.ts"] ستنتج ملفات الإخراج ["a.js", "b.js"] ،
لكن مجموعة ملفات الإدخال ["src/a.ts", "b.ts"] ستنتج ملفات الإخراج ["src/a.js", "b.js"] .

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

لا دائرية

بطبيعة الحال ، قد لا تشكل المشاريع رسمًا بيانيًا بأي دائرية. (TODO: ما هي المشاكل التي يسببها هذا بالفعل ، بخلاف كوابيس تزامن البناء؟) إذا حدث ذلك ، سترى رسالة خطأ تشير إلى المسار الدائري الذي تم تشكيله:

TS6187: Project references may not form a circular graph. Cycle detected:
    C:/github/project-references-demo/core/tsconfig.json ->
    C:/github/project-references-demo/zoo/tsconfig.json ->
    C:/github/project-references-demo/animals/tsconfig.json ->
    C:/github/project-references-demo/core/tsconfig.json

tsbuild

هذا الاقتراح غامض عن قصد حول كيفية استخدامه في نظام بناء "حقيقي". يتخطى عدد قليل جدًا من المشاريع حد 50،000 LOC "السريع" بدون تقديم شيء آخر غير tsc لتجميع كود ts.

سيناريو المستخدم "لا يمكنك إنشاء foo لأن bar لم يتم إنشاؤه بعد" هو نوع واضح من المهمة "Go fetch that" التي يجب أن يتولى الكمبيوتر العناية بها ، بدلاً من ذلك من عبء ذهني على المطورين.

نتوقع أن أدوات مثل gulp ، webpack ، إلخ ، (أو ملحقات TS الخاصة بها) ستبني في فهم مراجع المشروع والتعامل بشكل صحيح مع تبعيات البناء هذه ، بما في ذلك الفحص المحدث.

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

  • فحص سريع محدث
  • ترتيب الرسم البياني للمشروع
  • بناء التوازي
  • (TODO: آخرون؟)

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

لكى يفعل

الأقسام المراد ملؤها لإكمال هذا الاقتراح بالكامل

  • كيف يمكنك نقل مشروع قائم

    • ما عليك سوى إسقاط ملفات tsconfig.json ثم إضافة المراجع اللازمة لإصلاح أخطاء الإنشاء

  • التأثير على baseUrl

    • يجعل التنفيذ صعبًا ولكن لا يكون له تأثير فعال على المستخدم النهائي

  • مناقشة موجزة لمشاريع التداخل (TL ، DR يجب السماح بها)
  • سيناريو مخطط لتقسيم المشاريع التي نمت "كبيرة جدا" إلى مشاريع أصغر دون كسر المستهلكين
  • اكتشف سيناريو ليرنا

    • تقول نقطة البيانات المتاحة (N = 1) إنهم لن يحتاجوا إلى هذا لأن بنائهم منظم بالفعل بهذه الطريقة

    • ابحث عن المزيد من الأمثلة أو الأمثلة المضادة لفهم كيفية قيام الأشخاص بذلك بشكل أفضل

  • هل نحتاج إلى إعداد dtsEmitOnly للأشخاص الذين يقومون بتوصيل JS من خلال على سبيل المثال webpack / babel / rollup؟

    • ربما يشير هذا إلى references + noEmit

رائع!

اكتشف سيناريو ليرنا

  • تقول نقطة البيانات المتاحة (N = 1) إنهم لن يحتاجوا إلى هذا لأن بنائهم منظم بالفعل بهذه الطريقة

هل "هذا" يشير إلى الاقتراح أو تنفيذ بناء المرجع؟ بينما يمكنك استخدام lerna للقيام بالبناء (يقوم فريقي بذلك) ، إلا أنه سيكون أكثر فاعلية إذا اهتمت TS (أو أداة مبنية من هذا الاقتراح) بنفسها.

قسم TODO هو TODO للمقترح بأكمله

لطيف - جيد!

يجب أن يحتوي أي مشروع تتم الإشارة إليه على مصفوفة مراجع (قد تكون فارغة).

هل هذا ضروري حقا؟ ألن يكون كافيا إذا كانت هذه الحزمة بها ملفات .d.ts ؟
(في هذه الحالة ، قد لا يكون ضروريًا حتى لوجود tsconfig.json أيضًا؟)

حالة الاستخدام الخاصة بي: ضع في اعتبارك مشروعًا (مثل جهة خارجية) لا يستخدم outDir ، لذا فإن .ts و .js و .d.ts سيكون بجوار بعضهما البعض ، وسيحاول TS حاليًا تجميع .ts بدلاً من استخدام .d.ts .

السبب في عدم استخدام outDir بالنسبة لي هو السماح بسهولة أكبر للواردات على نمط import "package/subthing" ، والتي قد تكون على سبيل المثال import "package/dist/subthing" مع outDir: "dist" .
وأن تكون قادرًا على استخدام حزمة NPM أو مصدرها مباشرة (على سبيل المثال مع npm link ).

(سيكون من المفيد إذا سمح package.json بتحديد دليل بـ main ، لكن للأسف ...)

هل نحتاج إلى إعداد dtsEmitOnly للأشخاص الذين يقومون بتوصيل JS من خلال على سبيل المثال webpack / babel / rollup؟

على الاطلاق! هذه قطعة كبيرة مفقودة في الوقت الحالي. يمكنك حاليًا الحصول على ملف d.ts واحد عند استخدام outFile ، ولكن عند التبديل إلى الوحدات النمطية واستخدام التجميع ، فإنك تفقد هذا. ستكون القدرة على إرسال ملف d.ts واحد لنقطة دخول الوحدة النمطية (مع export as namespace MyLib ) أمرًا رائعًا. أعلم أن الأدوات الخارجية يمكنها القيام بذلك ، لكن سيكون من الرائع حقًا أن يتم دمجها في خدمات الإرسال واللغة.

هل هذا ضروري حقا؟ ألا يكفي أن تحتوي هذه الحزمة على ملفات .d.ts؟

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

يتماشى هذا الاقتراح بشكل وثيق مع كيفية هيكلة مشاريع TypeScript الخاصة بنا بالفعل. لقد قمنا بتقسيمنا إلى وحدات أصغر تحتوي كل منها على tsconfig.json ويتم بناؤها بشكل مستقل من خلال البلع. تشير المشاريع إلى بعضها البعض بالرجوع إلى ملفات d.ts.

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

نحتاج إلى شيء في tsconfig الهدف يخبرنا أين نتوقع أن تكون ملفات الإخراج.

هذا صحيح فقط عند استخدام outDir ، أليس كذلك؟

كما في: إذا كان لدي tsconfig أن:

  • لا تستخدم outDir (لكن لديها declaration: true بالطبع) ، إذن نحن لا نحتاج rootDir ، ولا references
  • لديها outDir ، إذن ستحتاج إلى references و / أو rootDirdeclaration: true ) ليتم تعيينها

سبب السؤال هو أنه يمكنني بعد ذلك تمكين "وضع المشروع" لأي حزمة TS بمجرد الرجوع إليها ، أي أنها تحت سيطرتي.

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

على سبيل المثال ، ضع في اعتبارك حزم NPM MyApp و SomeLib.
قد يحتوي SomeLib على tsconfig: declaration: true .

المستودع مثل:

package.json
tsconfig.json
index.ts
sub.ts

عند تجميعها ، يصبح هذا:

package.json
tsconfig.json
index.ts
index.d.ts
index.js
sub.ts
sub.d.ts
sub.js

هذا الهيكل يتيح على سبيل المثال

// somewhere in MyApp
import something from "SomeLib/sub";

في حزمة NPM المنشورة ، يتعين علي حاليًا دائمًا تجريد ملفات .ts ، وإلا فسيتم إعادة ترجمة جميع المصادر بواسطة TS إذا كان MyApp يستخدم SomeLib:

لذلك ، في NPM ، يصبح هذا:

package.json
index.d.ts
index.js
sub.d.ts
sub.js

الآن ، إذا وضعت references: ["SomeLib"] في ملف tsconfig الخاص بـ MyApp ، فسيكون من الجيد أن يعمل "كما هو" لكل من إصدار NPM والإصدار المصدر من SomeLib ، أي أنه لن يشتكي من فقدان tsconfig على سبيل المثال ، طالما أنه يجد sub.d.ts في المكان المناسب.


سؤال ذو صلة ولكن مختلف:

أدرك الآن أنه إذا وضع مؤلف SomeLib references في tsconfig الخاص به ، فإن هذا سيسمح بنشر حزم NPM مع ملفات .ts ، في المستقبل. ولكن بعد ذلك ، أفترض أن TS ستظل دائمًا تعيد ترجمة هذه عندما لا تضع أي حزمة تابعة صراحةً references: ["SomeLib"] في tsconfig الخاص بهم.

أم أن النية أيضًا أن يقدم references في MyLib تلقائيًا أيضًا "حدود المشروع" عندما يكون import 'فقط (أي ليس references ' في ذلك)؟

IIRC ، كانت إحدى الأفكار الأولية أنه إذا تم تحديد موقع على سبيل المثال من خلال node_modules ، فسيتم تفضيل ملفات .d.ts ملفات .ts ، ولكن تم تغيير هذا لاحقًا مرة أخرى ، لأن الكشف عن مجريات الأمور ("من خلال node_modules ") كان مشكلة للغاية بشكل عام. هل يمكن أن يؤدي وجود "حدود مشروع" صريحة إلى حل هذه المشكلة (على سبيل المثال ، projectRoot: true ، بدلاً من أو بالإضافة إلى وجود references

بالنسبة لقضية lerna ، كنت أتمنى التوصل إلى حل أبسط.

  1. في أدلة الحزم الفردية ، يجب ألا تعرف الحزم أي شيء يتعلق ببنية monorepo. يجب ألا تحتوي ملفات tsconfig json الفردية على أي مراجع.

    • يسمح لك هذا بتقسيم الحزم الفردية إلى مستودعات منفصلة والحصول ببساطة على أدوات الريبو الرئيسية لاستنساخها مثل ProseMirror: https://github.com/ProseMirror/prosemirror

  2. في ريبو "مساحة العمل" الجذر (الذي يمكن أن يحتوي على جميع التعليمات البرمجية ، ولكن يمكنه أيضًا استنساخ مستودعات أخرى) ، احصل على المراجع في tsconfig.json الخاص به

    • يتم ذلك فقط حتى تتمكن الأدوات من التعرف على المراجع ومتابعتها على طول الطريق إلى المصدر بدلاً من الدخول في ملفات .d.ts.

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

إضافة المفهوم الجديد لـ "مساحة العمل" tsconfig.json يحل هذه المشكلة. بهذه الطريقة ، إذا كنت مثلاً "git clone" للحزمة الفردية ، فإن تثبيت تبعياتها بالطريقة العادية (على سبيل المثال باستخدام npm أو الغزل) يجب أن يتيح لك العمل عليها بشكل منفصل ، لأن التبعيات المترجمة ستجلب ملفات تعريفها. إذا قمت باستنساخ مساحة العمل بالكامل وقمت بتشغيل الأمر لإحضار جميع الحزم ، فسيتيح لك تكوين مساحة العمل التنقل عبر جميع المصادر.

لاحظ أن مساحة العمل tsconfig.json تتوافق أيضًا بشكل مثالي مع مساحة عمل Yarn package.json https://yarnpkg.com/lang/en/docs/workspaces/

لقد قدمت دليلًا بسيطًا على المفهوم هنا

https://github.com/spion/typescript-workspace-plugin

ما عليك سوى إضافة المكون الإضافي إلى جميع ملفات tsconfig.json الخاصة بمستودعات إعادة الشراء الفردية

{
  "plugins": [{"name": "typescript-workspace-plugin"}]
}

ثم في toplevel package.json جنبًا إلى جنب مع إدخال "مساحات العمل" في yarn ، أضف إدخال "workspace-sources":

{
  "workspaces": ["packages/*"],
  "workspace-sources": {
    "*": ["packages/*/src"]
  }
}

يعمل هذا الحقل تمامًا مثل حقل "المسارات" في tsconfig.json ولكنه يؤثر فقط على خدمة اللغة للمشاريع الفردية ، ويوجهها إلى مصادر الحزم. يعيد وظيفة "الانتقال إلى التعريف / النوع" المناسبة وما شابه ذلك.

هذا صحيح فقط عند استخدام outDir ، أليس كذلك؟

صيح. لقد افترضنا أن كل شخص تقريبًا لديه مشروع كبير يستخدم outDir . سأكون مهتمًا بالسماع عن المشاريع التي لا تفعل ذلك

الآن ، إذا وضعت المراجع: ["SomeLib"] في tsconfig الخاص بـ MyApp ، فسيكون من الجيد أن تعمل "كما هي" لكل من إصدار NPM والإصدار المصدر من SomeLib

معجب كبير ، أحب هذه الفكرة كثيرًا. أحتاج إلى التفكير فيما إذا كان ذلك مطلوبًا حقًا أم لا.

أحد التحذيرات هنا هو أنني أعتقد أن مؤلفي الحزم يحتاجون إما إلى أ) نشر كل من ملفات .ts و tsconfig معًا في مكان حيث يجدها TS ، أو ب) لا ينشروا

أم أن النية أيضًا أن المراجع في MyLib ستقدم تلقائيًا أيضًا "حدود المشروع" عند استيراده فقط (أي عدم الإشارة إليه)؟

تحدثنا مع mhegazy ونعتقد أن هناك بالفعل نموذجًا بسيطًا لكيفية سلوك مراجع المشروع: أي مشروع بمصفوفة references لا "يرى" .ts خارج مجلد المشروع - وهذا يتضمن الملفات تحت exclude d من الدلائل. هذا التغيير وحده يجعل سيناريو lerna يعمل ("العمل" بمعنى "يتم حل مراجع الوحدة النمطية دائمًا إلى .d.ts") خارج المربع ، بالإضافة إلى الآخرين.

أحتاج إلى إلقاء نظرة على نموذج "مساحة العمل" أكثر.

هذا صحيح فقط عند استخدام outDir ، أليس كذلك؟

صيح. لقد افترضنا أن كل شخص تقريبًا لديه مشروع كبير يستخدم outDir. سأكون مهتمًا بالسماع عن المشاريع التي لا تفعل ذلك

لدينا 67 مشروع TS في حل الاستوديو المرئي والتي تم تجميعها بدون outdir و grunttasks postbuild لإنشاء هيكل دليل الإخراج (و uglify والمعالجة اللاحقة الأخرى).

معظم المشاريع لديها مثل هذا الملف tsconfig.json

 "include": [
    "../baseProj/Lib/jquery.d.ts",
    "../baseProj/baseProj.d.ts"
  ]

لقد استغرقت بعض الوقت لقراءة اقتراح المراجع ، وصححت - لا يحتاج مستخدمو مساحة عمل AFAICT lerna والغزل إلى أي من وظائف مساحة العمل المقترحة هنا:

  1. لدينا بالفعل رسم بياني تبعية يعتمد على package.json حتى نعرف الترتيب الذي سيتم تشغيل الإنشاء به. في الواقع ، يحتوي lerna على أمر تشغيل عام يمكنه تشغيل هذا بالترتيب ، وليس من الصعب كتابة أداة تضيف التوازي عند الاقتضاء. skipLibCheck يجب أن يجعل تأثير الأداء ضئيلًا ، لكني لم أتحقق منه.
  2. تقوم Lerna and Yarn بالفعل بإنشاء روابط رمزية للوحدات النمطية الأخرى في موقع node_modules المناسب. نتيجة لذلك ، يمكن لجميع المعالين اتباع حزمة الوحدة النمطية الأخرى. json ، وقراءة حقل الأنواع / الكتابة والعثور على ملف تعريف نوع module.d.ts المشار إليه.

ما ليس لدينا ، وما يوفره المكون الإضافي الذي كتبته ، هو طريقة لتحميل جميع المصادر في نفس الوقت. عندما أحتاج إلى إجراء تغييرات على وحدتين أو أكثر في نفس الوقت ، لا أريد "الانتقال إلى التعريف" و "الانتقال إلى تعريف النوع" لإرسالني إلى ملف .d.ts. أريده أن يرسلني إلى موقع كود المصدر الأصلي ، حتى أتمكن من تحريره. خلاف ذلك ، سأقوم فقط بتحميل دليل المشروع الفردي وستعمل الروابط الرمزية node_modules التي أنشأتها lerna / yarn.

نفس الشيء بالنسبة لنا. بدلاً من Lerna ، نستخدم Rush لحساب الرسم البياني للتبعية ، لكن التأثير هو نفسه. عندما نبني المشاريع ، فإن tsc هو مجرد واحدة من العديد من المهام التي يجب تشغيلها. يتم حساب خيارات المترجم لدينا من خلال نظام بناء أكبر ، ونحن ننتقل إلى نموذج حيث لا يكون tsconfig.json ملف إدخال ، ولكنه ناتج تم إنشاؤه (بشكل أساسي لصالح رمز VS).

ما ليس لدينا ، وما يوفره المكون الإضافي الذي كتبته ، هو طريقة لتحميل جميع المصادر في نفس الوقت. عندما أحتاج إلى إجراء تغييرات على وحدتين أو أكثر في نفس الوقت ، لا أريد "الانتقال إلى التعريف" و "الانتقال إلى تعريف النوع" لإرسالني إلى ملف .d.ts. أريده أن يرسلني إلى موقع كود المصدر الأصلي ، حتى أتمكن من تحريره.

+1 سيكون هذا رائعًا.

إذا كنا نحلم بدعم أفضل متعدد المشاريع ، فسيكون طلبي الأول خدمة مترجم ، مثل كيفية عمل VS Code IntelliSense. ستكون تصميماتنا أسرع بشكل ملحوظ إذا تمكن Rush من استدعاء tsc 100 مرة دون الحاجة إلى تدوير محرك المترجم 100 مرة. يعد المترجم أحد أغلى خطوات البناء لدينا. في monorepo ، تعتبر أوقات البناء مهمة حقًا.

MustafaHosny اللهم امين

نعم من فضلك!

أعتقد أن إحدى أكثر النتائج المفيدة لنظام المشروع ستكون إذا
انتقل "انتقل إلى التعريف" إلى الملف المصدر بدلاً من ملف d.ts و
بحث في "العثور على جميع المراجع" من خلال شجرة مرجع المشروع.

من المفترض أن يؤدي هذا أيضًا إلى فتح عمليات إعادة بناء نوع "إعادة تسمية عالمية".

يوم الخميس ، 9 تشرين الثاني (نوفمبر) 2017 الساعة 9:30 مساءً سالفاتور بريفتي [email protected]
كتب:

نعم من فضلك!

-
أنت تتلقى هذا لأنك مشترك في هذا الموضوع.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/Microsoft/TypeScript/issues/3469#issuecomment-343356868 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANX6d19Zz7TCd_GsP7Kzb-9XJAisG6Hks5s07VXgaJpZM4E-oPT
.

تحدثت مع mhegazy ونعتقد أن هناك في الواقع نموذجًا بسيطًا لكيفية إحالة المشروع إلى السلوك: أي مشروع به مصفوفة مراجع لا "يرى" ملفًا .ts خارج مجلد المشروع - وهذا يتضمن الملفات الموجودة ضمن الأدلة المستبعدة.

جميل ، وفي هذه الحالة ، لماذا يتعين على المرء تحديد أي مراجع محددة على الإطلاق؟
يبدو أنه يكفي وجود علامة (مثل projectRoot: true ).
على سبيل المثال ، ما الفرق بين references: ["foo"] و references: [] ؟
لأنني إذا أنا import "foo" أو import "bar" ، فسيتجاهل كلاهما أي ملفات .ts .

لذلك ، في هذه الحالة ، يصبح الاقتراح:

بالنظر إلى هذا tsconfig.json (TODO bikeshed on projectRoot ):

{
  "extends": "../tsproject.json",
  "compilerOptions": {
    "projectRoot": true
   }
}

عندما يحتاج tsc بعد ذلك إلى حل شيء ما خارج مجلد المشروع (بما في ذلك الملفات الموجودة ضمن الدلائل المستبعدة) ، سيبحث فقط في ملفات .d.ts (بدلاً من ذلك ، قد يكون فقط _prefer_ .d.ts الملفات ، والعودة إلى tsconfig و / أو .ts إذا رأى ذلك فقط).

هذا يجعل القرار أثناء التجميع سريعًا وبسيطًا.
إنه يعمل لمراجع monorepo (على سبيل المثال import "../foo" ) والمراجع القائمة على الحزم (مثل import "foo" ).
إنه يعمل مع حزم NPM وتمثيل كود المصدر الخاص بها.
كما أنه يزيل الحاجة إلى حل ماكينات tsconfig.json أثناء الترجمة ، على الرغم من أن رسالة الخطأ إذا لم تتمكن من العثور على .d.ts ستكون أقل فائدة.

يبدو الأمر جيدًا جدًا لدرجة يصعب تصديقها ، إذا كان الأمر بهذه البساطة حقًا ، لذلك ربما أتجاهل شيئًا مهمًا :)


كما يشير آخرون أيضًا ، لا يزال من المهم جدًا أن يستمر "IntelliSense" في العمل مع ملفات .ts.

لذلك ، إذا تم تقديم طلب لـ "الانتقال إلى التعريف" ، و "العثور على المراجع" وما إلى ذلك ، فيجب استخدام بعض التعيين العكسي لتحديد موقع ملف .ts المقابل من الملف .d.ts الذي استخدمه لذلك بعيد.

يمكن إجراء هذا التعيين باستخدام على سبيل المثال:

  • باستخدام سلسلة تعليق مضمنة مثل //# sourceURL = ../src/foo.ts في .d.ts

    • يمكن استخدام خريطة مصدر أكثر تفصيلاً للتعيين من "ملفوفة" .d.ts إلى الأصل .ts

  • حل ملف .js ، واستخدام خريطة المصدر الخاصة به لتحديد موقع ملفات .ts

هذا يقدم موضوع إعادة بناء .d.ts عندما يتم تغيير هذا .ts ، لكنني لست متأكدًا من أنه يجب حله من خلال هذا الاقتراح. على سبيل المثال ، هو الحال اليوم بالفعل أنه يجب أن تكون هناك عملية ما لإعادة إنشاء ملفات .js ، حتى من مشروع الجذر نفسه. لذلك أفترض أنه سيكون من الآمن افتراض أنه إذا كان ذلك موجودًا ، فسيكون هناك أيضًا شيء لإعادة بناء التبعيات. يمكن أن تكون مجموعة من tsc موازية لكل حزمة ، يمكن أن تكون tsbuild ، يمكن أن تكون IDE ذكية بسلوك يشبه compileOnSave ، إلخ.

pgonzalmichaelaird https://github.com/spion/typescript-workspace-plugin يفعل ذلك فحسب - بل يعيد تذهب إلى تعريف وتجد كل المراجع عن tsconfig متعددة الغزل / lerna / الخ مساحة عمل المشروع.

مثير للاهتمام ... أتساءل عما إذا كان بإمكاننا جعل هذا العمل مع Rush. سوف نلقي نظرة.

لمعلوماتك ، هناك أداة بسيطة أخرى أنشأناها كجزء من هذا الجهد وهي wsrun

على غرار lerna run ، يقوم بتشغيل أمر لجميع الحزم في مساحة العمل.

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

مجرد ملاحظة ، oao هي أداة monorepo أخرى للغزل. وقد أضاف مؤخرًا دعمًا للترتيب "الطوبولوجي" للأوامر أيضًا.

أود فقط أن أنشر كلمة "إعادة هيكلة" هنا لأنها هدف مهم بالنسبة لنا ، على الرغم من أنها قد تكون عرضية للاقتراح الحالي (https://github.com/Microsoft/TypeScript/issues/3469#issuecomment-341317069) و لم يرد ذكرها في هذه المسألة كثيرًا.

حالة الاستخدام الخاصة بنا هي monorepo مع العديد من مشاريع TS ، ويمكن تقليلها بشكل أساسي إلى common-library بالإضافة إلى اثنين من التطبيقات: app1 و app2 . عند العمل في IDE ، يجب التعامل مع هؤلاء كمشروع واحد ، على سبيل المثال ، يجب أن تعمل إعادة تسمية إعادة البناء عبر جميع الوحدات الثلاث ، ولكن app1 و app2 هما أيضًا هدفان منفصلان للبناء. بينما أوافق على أن الإنشاء هو مصدر قلق منفصل بشكل عام ، فإن الحقيقة هي أن تطبيقاتنا صغيرة جدًا وأن القيام بشيء مثل cd app1 && tsc سيكون جيدًا بالنسبة لنا.

إذا توصل TypeScript إلى طريقة جيدة لدعم ذلك ، فسيكون ذلك رائعًا.

بالنسبة لإعادة بناء / مراجع monorepo عبر المشاريع ، وجدت أن هذا الإعداد يعمل بالنسبة لي إذا كنت تعمل في vscode:

الجذر tsconfig:

"compilerOptions": {
   "baseUrl": ".",
   // global types are different per project
   "types": [],
   "paths": {
      "lib": ["packages/lib/src"],
      "xyz1": ["packages/xyz1/src"],
      "xyz2": ["packages/xyz2/src"],
   }
},
"include": ["./stub.ts"], // empty file with export {} to stop vscode complaining about no input files
"exclude": ["node_modules"]

الحزم / xyz1 / tsconfig.json

{
  "extends": "../../tsconfig",
   "compilerOptions": {
      "types": ["node"],
   },
   "include": ["src/**/*"]
}

الحزم / xyz2 / tsconfig.json

{
  "extends": "../../tsconfig",
   "compilerOptions": {
      "types": ["webpack-env"]
   },
  "include": ["src/**/*"]
} 

الحزم / lib / tsconfig.json

{
   "extends": "../../tsconfig",
    "compilerOptions": { ... },
    "include": ["src/**/*"],
    // special file to load referenced projects when inside in lib package, without it they won't be 
    // visible until you open some file in these projects 
    "files": ["./references.ts"],
}

الحزم / lib / tsconfig-build.json

{
   "extends": "./tsconfig",
    // exclude referenced projects when building
   "files": []
}

حزم / ليب / مراجع

import "xyz1";
import "xyz2";

export {};

تحتاج إلى الخاصية الصحيحة main في الحزمة package.json وقد تكون types حتى بالنسبة للحزم no-lib ، على سبيل المثال:

  "main": "src/main.tsx",
  "types": "src/main.tsx",

بهذه الطريقة ، فإن إعادة بناء / إعادة تسمية شيء ما في lib ستؤدي أيضًا إلى إعادة بناء المراجع في xyz1 و xyz2 . يمكن أيضًا أن تحتوي المشاريع على مناطق كروية / مستهدفة مختلفة بهذه الطريقة.

في Gradle ، يسمونه ببساطة - البناء المركب .

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

شكرا!
مستقبل مشرق لـ TypeScript.

لدي نموذج أولي أود أن يجربه الأشخاص إذا كانوا يستخدمون مسارات وحدة نمطية نسبية. هناك عينة من الريبو على https://github.com/RyanCavanaugh/project-references-demo والتي تحدد السيناريو الأساسي وتوضح كيف يعمل.

للتجربة محليًا:

git clone https://github.com/RyanCavanaugh/TypeScript
git checkout pr-lkg
npm install
npm run build
npm link

ثم في مجلدك الآخر:

npm link typescript

سأحتفظ بعلامة pr-lkg تشير إلى التزام العمل الأخير مع تغير الأشياء. بعد ذلك في قائمة المهام الخاصة بي:

  • [x] أضف رسائل خطأ أفضل عندما لا يتم إنشاء مشاريع تابعة
  • [] قم بتطبيق سلوك إعادة التوجيه على مسارات الوحدة غير النسبية
  • [] كشف واجهة برمجة تطبيقات لأدوات البناء للاستهلاك

RyanCavanaugh لا يمكنني حقًا del أو Error: Cannot find module 'C:\github\TypeScript\built\local\tsc.js' (ربما المسار المحلي الخاص بك؟) ولكن بشكل عام ، يبدو الهيكل رائعًا.

هل هذا tsc - فقط أم أنه سيحسب أيضًا عمليات إعادة البناء على مستوى المشروع في VSCode مع خادم اللغة؟

... أيضًا علامة pr-lkg مفقودة.

العلامة موجودة (ليست فرعًا). راجع https://github.com/RyanCavanaugh/TypeScript/tree/pr-lkg

references في tsconfig.json هو تمكين لكل تبعية ، ألن يكون من المنطقي تطبيقه على كل ما يتم حله خارج rootDir ؟

أتخيل شيئًا مثل خاصية sandbox يمكن أن تبدو مثل:

# tsconfig.json
{
  "compilerOptions": {
    "outDir": "lib",
    "sandbox": "."
  },
  "include": ["src/index.ts"]
}

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

# package.json
{
  "name": "animals",
  "module": "src",
  "typings": "lib",
  "dependencies": {
    "core": "*"
  }
}

من هنا:

  • لا يتعين عليك الاحتفاظ بقائمتين متزامنتين ( references و dependencies ).
  • الحزمة ليس لديها معرفة بنظام الملفات خارج النظام الخاص بها.
  • استخدم إستراتيجية دقة وحدة العقدة بدلاً من المسارات المخصصة.

RyanCavanaugh ، على حد هذه التغييرات ولن أتمكن من إرسال مثل هذه المشاريع للاختبار ، على سبيل المثال ، على travis-ci.org. حق؟

ملاحظات من اجتماع اليوم مع بيلتي / mhegazy


  • يجب أن يعمل البحث عن المراجع / إعادة التسمية ، على الأقل بالنسبة للسيناريوهات التي يكون فيها سياق التجميع الضروري لتحديد إغلاق المشاريع مناسبًا للذاكرة
  • ستعمل إعادة التسمية على مستوى الحل على البحث عن ملف "الحل" ، والعمل بشكل عكسي للعثور على مشاريع مرجعية ، ثم التنفيذ - تحميل أقسام الرسم البياني التي يظهر منها الرمز. قد تكون هذه عملية تكرارية للعثور على إعلان المنشأ الحقيقي
  • يحتاج tsbuild للتعامل مع الوضع -w
  • قد لا يكون للحلول مشاريع فرعية تنشأ خارج مجلد الحل
  • تحتاج إلى وثائق واضحة على سبيل المثال gulp ، webpack

الشريط الجانبي: إعادة التسمية هذه لا تعمل اليوم

function f() {
  if (Math.random() > 0.5) {
    return { foo: 10 };
  } else {
    return { foo: 20 };
}
// rename foo here doesn't rename *both* instances in the function body
f().foo;

شكرا ريان ومحمد وبيل. كان الحصول على سيناريو البحث عن المراجع / إعادة التسمية الذي يعمل عبر المشاريع إحدى حالات الاستخدام الأساسية التي كنت أفكر فيها عندما قدمت الشكوى الأصلية حول عدم دعم TypeScript للمشاريع متوسطة الحجم. المشاريع المتوسطة الحجم معيارية ولكنها ليست كبيرة. الاقتراح والعمل الذي رأيته هنا حتى الآن يشبه إلى حد كبير مسرحية قابلة للتوسع. هذا مهم للغاية لصحة TypeScript على المدى الطويل ، لكنه في الغالب مفيد للمشاريع الكبيرة ، وليس المتوسطة. تبدو الأشياء التي أسمعها في هذا التعليق من Ryan على غرار ما هو مطلوب لتحسين بيئة العمل لتطوير المشاريع متوسطة الحجم في TypeScript.

كالعادة ، شكرًا جزيلاً لفريق TypeScript بأكمله على جهودك! أنت تقوم بعمل رائع.

هناك خدعة مع مساحة عمل lerna / yarn ستجعل حياتك أسهل بكثير.
قم بتوجيه الإدخالات main و types في الحزمة الخاصة بك. json من المشاريع الفرعية إلى src / index. ts ، وسيعمل سيناريو البحث عن المراجع / إعادة التسمية.
وستكون قادرًا على تجميع مشروعك بالكامل باستخدام tsc واحد قيد التشغيل.
يمكنك القيام بذلك لبعض الحزم الخاصة بك ، يمكنك القيام بذلك للجميع. مكالمتك.

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

مع الإعداد أعلاه ، حصلت على أكثر أو أقل من جميع الميزات المتوقعة

إليك خدعة مع مساحة عمل lerna / الغزل ستجعل حياتك أسهل كثيرًا.
قم بتوجيه الإدخالات الرئيسية والأنواع الموجودة في package.json الخاصة بالمشاريع الفرعية إلى ملف src / index.ts الخاص بك ، وسيعمل سيناريو Find References / Rename (البحث عن المراجع / إعادة التسمية) ببساطة.

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

  • يتم تجميع الحزم الخارجية عدة مرات ، في كل مرة باستخدام tsconfig للحزمة _requiring_. إذا كانت الحزم المطلوبة تحتوي على tsconfigs مختلفة (مثل libs مختلفة) ، فقد يتسبب ذلك في ظهور أخطاء تجميع خاطئة على الحزمة المطلوبة حتى يتم تجميعها مرة أخرى.

  • الحزم المطلوبة يتم تجميعها بشكل أبطأ لأنها تتضمن ملفات أكثر من اللازم.

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

في مشاريعنا استبعدنا الاعتماد على ملفات TS بسبب العيوب. جميع التبعيات بين الحزم موجودة في ملفات index.d.ts ، لذلك يعاملها المترجم على أنها خارجية وكلها جيدة.

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

أتفق مع بعض المشاعر الأخرى - الكتابة المطبوعة هي مترجم ، وليس نظام بناء. نحتاج إلى أدواتنا لدعم إنشاءات متعددة المشاريع بشكل أفضل. أعلم أن هناك بعض الخيارات في المجتمع تبدأ في القيام بذلك. كمثال ، يحتوي C # على مترجم يسمى Roslyn وأداة بناء تسمى MSBuild.

ناقش اليوم مع التسمية تعمل بأقل قدر ممكن من الألم.

تبدو الحالة الأسوأ غير المتدهورة لإعادة التسمية كما يلي:

// alpha.ts
const v = { a: 1 };
export function f() { return v; }
export function g() { return v; }

// alpha.d.ts (generated)
export function f(): { a: number };
export function g(): { a: number };

// beta.ts (in another project)
import { f } from '../etc/alpha';
f().a;

// gamma.ts (in yet another project)
import { g } from '../etc/alpha';
g().a;

الملاحظة الرئيسية هي أنه من المستحيل معرفة أن إعادة تسمية f().a يجب أن تعيد تسمية g().a إلا إذا كان بإمكانك رؤية alpha.ts للربط بين الاثنين.

رسم تقريبي لخطة التنفيذ:

  • احصل على تمثيلات SourceFile "الغنية" و "الهزيلة" في الذاكرة لملفات .d.ts. قراءة ملفات "Lean" من القرص ؛ يتم إنتاج "الأغنياء" نتيجة لتوليد .d.s في الذاكرة
  • تحتوي ملفات المصدر "الغنية" .d.ts على مراجع من عقد المعرف الخاصة بها إلى الاسم (الأسماء) الأصلي في الملف المصدر الأصلي
  • أثناء إعادة التسمية ، ننتقل أولاً إلى الرمز المعني ، كالمعتاد. إذا نشأ هذا في ملف d.ts المشار إليه في المشروع ، فنحن نحمّله وننشئ ملف d.ts "Rich" الخاص به

    • ملاحظة: هذه العملية تكرارية ، أي أنها قد تتطلب تتبع عدة مستويات إلى أن تصل إلى ملف تنفيذ حقيقي (أحد الملفات التي ليست إعادة توجيه d.ts بسبب مرجع المشروع)

  • الآن استخدم المؤشرات "rich" لمعرفة المعرفات الأخرى في المشروع .d.ts تنشأ من نفس معرف الملف المصدر
  • في كل مشروع متلقٍ للمعلومات ، قم بإجراء مسح نصي للمعرف الذي تمت إعادة تسميته ومعرفة ما إذا كانت نتيجة "go-to-def" الخاصة به هي أي من مواقع "البدء من نفس الرمز" في ملفات .d.ts
  • قم بإجراء إعادة التسمية في ملف التنفيذ

RyanCavanaugh ستذهب إلى التعريف / تجد كل المراجع ستعمل مع هذا النموذج؟

ملاحظات من مناقشة سابقة مع أندرس ومحمد حول عدد كبير من الأسئلة المفتوحة

  • هل ينطبق prepend أيضًا على .d.ts ؟ نعم
  • ماذا نفعل بـ @internal في فرع طعام الكلاب؟ نحتاج إلى الاحتفاظ بالإعلانات الداخلية في ملفات .d.ts المحلية ولكن لا نريدها أن تظهر في إصدارات الإخراج

    • إزالة --stripInternal

    • لكن لا تستنكره (حتى الآن ...؟)

    • رايان يكتب أداة remove-internal (مكتمل)

    • بنيت -> عملية LKG تزيل الإعلانات @internal

  • ماذا يحدث إذا قمت بتغيير ملف .d.ts من على سبيل المثال @types ؟

    • تحتاج إلى فرض إعادة بناء يدويًا إذا كنت تريد رؤية أخطاء جديدة محتملة ☹️

    • يمكن في النهاية كتابة ملف "files I look at.txt" إلى مجلد الإخراج إذا أصبح هذا يمثل مشكلة بالفعل

  • هل noEmitOnError إلزامي؟ نعم فعلا.

    • وإلا فإن عمليات إعادة البناء ستخفي الأخطاء!

  • referenceTarget -> composable ✨ 🚲 🏡 ✨
  • ماذا عن مشاريع العقدة الورقية التي لا تريد إصدار إعلان ، ولكنها تريد إعادة بناء سريع؟

    • tsbuild أو ما يعادله التحقق لمعرفة مدى امتثالهم للمتطلبات غير ذات الصلة بالمستقبل composable

  • المراجع الدائرية ، (كيف) تعمل؟

    • بشكل افتراضي ، لا

    • يمكنك تحديد مثال { path: "../blah", circular: true } إذا كنت تريد القيام بذلك

    • إذا قمت بذلك ، فالأمر متروك لك للتأكد من أن البناء الخاص بك حتمي ويصل دائمًا إلى نقطة ثابتة (ربما لا؟!)

    • إعادة تخطيط التعميم: الاستيراد اختيارية (ولكن ذات أولوية)

المنوعات

  • weswigham لديه فكرة بديلة لإعادة التسمية نحتاج لمناقشتها مع

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

تضمين التغريدة
هل يجب إعادة تسمية / البحث عن جميع المراجع التي تعمل عبر المشاريع المشار إليها بعد دمج # 23944؟ هل يجب أيضًا استخدام composite: true و projectReferences: [] في حالة الحاجة إلى خدمات اللغة فقط (ولكن ليس tsbuild)؟

هل يجب إعادة تسمية / البحث عن جميع المراجع التي تعمل عبر المشاريع المشار إليها بعد دمج # 23944؟

ليس بعد. لكننا نعمل على هذا بعد ذلك.

يجب أيضًا استخدام مركب: صحيح ومراجع مشروع: [] في حالة الحاجة إلى خدمات اللغة فقط (ولكن ليس tsbuild)؟

لست متأكدًا من فهمي للسؤال .. ماذا تقصد "خدمة اللغة" وليس "بناء"؟

لست متأكدًا من فهمي للسؤال .. ماذا تقصد "خدمة اللغة" وليس "بناء"؟

أنا مهتم فقط بدعم المحرر (إعادة تسمية / العثور على جميع المراجع / إلخ ...) عبر مشاريع متعددة في monorepo ، وليس في أداة الإنشاء الجديدة (المعروف أيضًا باسم build mode ) (# 22997) لأنني أستخدم بابل لتجميع بلدي.

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

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

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

في الأساس ، بدلاً من:

"dependencies": [
    "../common", 
    "../util"
],

هل يمكننا من فضلك

"dependencies": [
    "common", 
    "util"
],

ولها مساحة عمل tsconfig.json

"workspace": {
  "common": "packages/common",
  "util": "packages/util"
}

أو الأفضل من ذلك ، بناء جملة المسارات:

"workspace": {
  "*":"packages/*"
}

فوائد:

  • القدرة على تحديد قواعد بحث مختلفة اعتمادًا على نظام الوحدة
  • القدرة على الرجوع إلى node_modules على سبيل المثال عند تنزيل الحزمة خارج مساحة العمل
  • القدرة على تجميع مساحات عمل متعددة بحرية للعمل عليها عن طريق استنساخ عدة مستودعات وتكوين مختلف للمسارات ، بحيث يمكنك العمل على المزيد من الحزم بالتوازي.

أو على الأقل ، هل يمكننا الاحتفاظ بالأسماء التي لا تحتوي على مسارات (تلك التي لا تبدأ بـ "./" أو "../") محفوظة للاستخدام في المستقبل ...

لست متأكدًا من مدى ارتباط ذلك ، لكن Yarn 1.7 قدم مفهوم "مساحات العمل المركزة" مؤخرًا ، راجع منشور المدونة هذا .

هل هناك أي شخص هنا على دراية كافية بمساحات العمل والعمل الذي تقوم بهRyanCavanaugh حول مراجع / وضع بناء مشروع TypeScript لإسقاط تعليق يشرح ما إذا كانت مرتبطة على الإطلاق؟ شعوري الداخلي هو أن _ في مكان ما_ بين مساحات عمل Yarn (ستحصل عليها npm أيضًا هذا العام) وإصدارات TypeScript المستقبلية تكمن في دعم جيد لل monorepos مع العديد من المشاريع والمكتبات المشتركة. (نشعر بالألم حاليًا).

أرغب حقًا في الحصول على تحديث بشأن تقدم هذه الميزة. نحن نخطط لنقل Aurelia vNext إلى monorepo في الشهر المقبل أو نحو ذلك. نسختنا الجديدة هي 100٪ TypeScript ونود استخدام نظام مشروع TS رسمي بدلاً من Lerna ، إذا استطعنا. يسعدنا أيضًا أن نكون من أوائل المستخدمين / المختبرين للميزات الجديدة :)

تمت إضافة الدعم الأساسي والتعريف باستخدام دعم tsc --b لدعم البناء موجود بالفعل ومرتبط بـ TS 3.0. تم نقل قاعدة التعليمات البرمجية المطبوعة لاستخدامها. نقوم حاليًا باختبار هذا الدعم باستخدام الريبو المطبوع.

ما الذي لا يزال يتعين القيام به في هذه المرحلة: 1. احصل على جميع المراجع / إعادة التسمية للعمل على سيناريوهات متعددة المشاريع. 2. معالجة تحديث ملفات d.ts في الخلفية في المحرر ، ودعم 3. --watch لسيناريوهات المشاريع المتعددة. الكثير والكثير من الاختبارات.

هذه التذكرة موجودة في الكتب منذ 3 سنوات. هل ما زلت 3/6 عناصر معلقة؟

claudeduguay هذا تغيير جوهري في المشاريع التي يدعمها TypeScript ، هل حان وقت الاحتفال ، ألا تعتقد ذلك؟ أنا سعيد للغاية لهذا!

mhegazy هذه أخبار رائعة. يسعدني جدًا أن أسمع أن فريق TS يقوم بتجربة ذلك في مشروعه الخاص أيضًا. نتطلع إلى الانتهاء من الأشياء القليلة الماضية والحصول على هذا كخيار لـ Aurelia :) بمجرد وجود بعض الوثائق حول إعداده ، سننقل vNext إلى نظام المشروع الجديد. لا استطيع الانتظار!

mhegazy هل يمكنك إلقاء بعض الضوء على كيفية عمل كل هذا مع ملفات ومشاريع package.json بناءً على وحدات ES2015؟ على سبيل المثال ، في Aurelia vNext ، لدينا حزم مثل @aurelia/kernel ، @aurelia/runtime ، @aurelia/jit ، إلخ. هذه هي أسماء الوحدات التي سيتم استخدامها في import البيانات في جميع أنحاء المشاريع المختلفة. كيف سيفهم مترجم TS أن أسماء الوحدات هذه ترتبط بالمجلدات المرجعية المختلفة؟ هل ستلتقط ملفات package.json الموضوعة في كل مجلد مرجعي؟ كيف سيختلف هذا عن مساحات عمل Lerna أو الغزل؟ إن نظري الأولي في الروابط أعلاه يجعلني أعتقد أنني سأحتاج إلى استخدام مشاريع TS (بناء) بالاشتراك مع Lerna (ربط النشر والنشر) للحصول على حل عملي ، لكنني لا أرى كيف ستبني TS بشكل صحيح إذا لم يتكامل مع package.json و node_modules. يختلف مصدر TS repo تمامًا عن متوسط ​​مشروع Lerna الخاص بك (لا شيء يشبهه حقًا) ، لذلك بدأت أتساءل عما إذا كان هذا سيكون قادرًا على تلبية احتياجاتنا. أي مزيد من المعلومات التي يمكنك توفيرها ، و esp. سيكون إعداد حل تجريبي عملي مشابه لما وصفته هنا مفيدًا جدًا. شكرا!

أشارك نفس الأسئلة مثلEisenbergEffect. على وجه الخصوص ، آمل أيضًا أن يعمل هذا بشكل جيد مع monorepo lerna .

سيناريوهان monorepo للنظر فيهما

لنبدأ بإعداد حيث قمت بربط كل شيء باستخدام lerna:

/packages
  /a
    /node_modules
      /b -> symlink to b with package.json "types" pointing to dist/index.d.ts
  /b
    /dist
      /index.d.ts -> built output of entry point declaration file

الشيء الأساسي الذي نريد حدوثه هنا هو إعادة إنشاء b لقد أنشأنا a iff a غير محدث. لذلك نضيف "references": [ { "path": "../b" } ] إلى a 's tsconfig.json ونشغل tsc --build في a للحصول على الإصدارات الأولية الصحيحة b . في هذا العالم ، تعمل مراجع المشروع ببساطة كتمثيل للرسم البياني للبناء وتسمح بإعادة بناء الزيادة بشكل أكثر ذكاءً. من الناحية المثالية ، يمكن أن تتعاون lerna و TS هنا وتعكس تبعيات package.json إلى tsconfig.json عند الاقتضاء.

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

{
  "compilerOptions": { "outDir": "bin" },
  "package": "@RyanCavanaugh/coolstuff"
}

ثم إضافة "references": [{ "path": "../cool" }] ستضيف تلقائيًا تعيين مسار من @RyanCavanaugh/coolstuff -> ../cool/bin/ . لم نقم بإضافة هذا بعد ولكن يمكننا النظر فيه إذا اتضح أنه سيناريو أكثر شيوعًا.

من الناحية المثالية ، يمكن أن تتعاون lerna و TS هنا وتعكس تبعيات package.json في tsconfig.json حيثما كان ذلك مناسبًا

بدلاً من الاعتماد على الأدوات الخارجية ، يمكننا اختيار قراءة package.json (بشرط أن يكون بجانب tsconfig الخاص بك) كمراجع محتملة إذا تم تعيين composite: true (تحقق لمعرفة ما إذا كانت كل حزمة تم حلها تحتوي على tsconfig.json ، إذا كان لديه واحد ، فاعتبره عقدة مشروع قابلة للبناء وتكرار). نظرًا لأن كل شيء مرتبط في مكانه الصحيح ، فلا ينبغي علينا حتى تغيير الدقة (كثيرًا؟ أي؟) للتعامل مع مساحة العمل. لا يقوم Lerna في الواقع بإعداد أي عناصر خاصة بـ ts (أو build-specifc) كما هو الحال مع afaik ، بل يقوم فقط بربط كل شيء في مكانه وإدارة الإصدار. سيكون هذا تحسينًا لما نقوم به اليوم ، وهو تحميل ملفات ts (نظرًا لأننا نفضل تلك الملفات على الإعلانات) وإعادة تجميع كل شيء بغض النظر عن التاريخ القديم.

RyanCavanaugh هذا يبدو مثيرًا جدًا. هل لديك أي فكرة عما إذا كانت ستعمل مع إستراتيجية Rush للربط الرمزي؟ باختصار ، ينشئ Rush حزمة تركيبية common / temp / package.json تحتوي على مجموعة شاملة من جميع التبعيات لجميع الحزم في الريبو. ثم نستخدم pnpm لإجراء عملية تثبيت واحدة لهذه الحزمة الاصطناعية. (يستخدم PNPM الارتباطات الرمزية لإنشاء رسم بياني لا دوري موجه بدلاً من هيكل شجرة NPM ، مما يلغي مثيلات المكتبة المكررة). ثم يقوم Rush بإنشاء مجلد node_modules لكل مشروع في الريبو ، مصنوع من روابط رمزية تشير إلى المجلدات المناسبة ضمن Common / temp . النتيجة متوافقة تمامًا مع TypeScript وخوارزمية دقة NodeJS القياسية. إنه سريع جدًا نظرًا لوجود ملف shrinkwrap واحد ومعادلة إصدار واحدة للريبو بالكامل ، مع السماح لكل حزمة بتحديد تبعياتها الخاصة.

نحن لا نضع أي شيء مميز في tsconfig.json لهذا النموذج. إذا كانت هناك حاجة إلى بعض إعدادات TypeScript الخاصة لميزة تعريف goto ، فنحن نرغب بشكل مثالي في إنشائها تلقائيًا أثناء التثبيت بدلاً من تخزينها في Git.

pgonzal شكرا على الارتباط إلى Rush! لم أر ذلك بعد. سوف أتحقق من ذلك الليلة.

RyanCavanaugh شكرا على الشرح. السيناريو الأول الخاص بك مع lerna هو الأقرب إلى ما لدينا. إليك UX repo مع TS و lerna كمثال على شيء نرغب في استخدام دعم المشروع الجديد على https://github.com/aurelia/ux

weswigham يبدو أن ما تصفه يناسب السيناريو أيضًا. مثال الريبو أعلاه.

لاحظ فقط أنه في حالة مساحات عمل الغزل ، لا يتم ربط الوحدات النمطية في دليل كل حزمة فردية ، بل يتم ربطها بشكل رمزي في مساحة العمل ذات المستوى الأعلى node_modules .

وهذا هو سبب اعتقادي أن المراجع التي لا تبدأ بنقطة ("./" أو "../") يجب حجزها للمستقبل. نأمل أن ينتهي الأمر بهذه "المراجع المسماة" ، ويتم التعامل معها عبر إستراتيجية دقة الوحدة النمطية النشطة بدلاً من التعامل معها كمسارات نسبية.

spion سنستخدم فقط اسم خاصية بخلاف path لذلك إذا لزم الأمر (على سبيل المثال "references": [ { "module": "@foo/baz" } ] )؛ لا أريد التسبب في حدوث ارتباك حيث يعني "bar" و "./bar" نفس الشيء في files لكن شيئًا مختلفًا في references

المستندات / blogpost العمل قيد التقدم أدناه (سيتم تعديل هذا بناءً على التعليقات)

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


مراجع المشروع

مراجع المشروع هي ميزة جديدة في TypeScript 3.0 تتيح لك هيكلة برامج TypeScript إلى أجزاء أصغر.

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

نقدم أيضًا وضعًا جديدًا لـ tsc ، علامة --build ، والتي تعمل جنبًا إلى جنب مع مراجع المشروع لتمكين عمليات إنشاء TypeScript بشكل أسرع.

مشروع مثال

دعنا نلقي نظرة على برنامج عادي إلى حد ما ونرى كيف يمكن لمراجع المشروع أن تساعدنا في تنظيمه بشكل أفضل.
تخيل أن لديك مشروعًا مكونًا من وحدتين ، converter و units ، وملف اختبار مطابق لكل منهما:

/src/converter.ts
/src/units.ts
/test/converter-tests.ts
/test/units-tests.ts
/tsconfig.json

تستورد ملفات الاختبار ملفات التنفيذ وتقوم ببعض الاختبارات:

// converter-tests.ts
import * as converter from "../converter";

assert.areEqual(converter.celsiusToFahrenheit(0), 32);

في السابق ، كان هذا الهيكل محرجًا إلى حد ما للعمل معه إذا كنت تستخدم ملف tsconfig واحدًا:

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

يمكنك استخدام ملفات tsconfig متعددة لحل بعض هذه المشكلات ، ولكن ستظهر مشكلات جديدة:

  • لا يوجد فحص مُحدّث مضمّن ، لذلك ينتهي بك الأمر دائمًا بتشغيل tsc مرتين
  • يؤدي استدعاء tsc مرتين إلى زيادة وقت بدء التشغيل
  • لا يمكن تشغيل tsc -w على ملفات تهيئة متعددة في وقت واحد

يمكن لمراجع المشروع أن تحل كل هذه المشاكل وأكثر.

ما هو مرجع المشروع؟

tsconfig.json لها خاصية جديدة من المستوى الأعلى ، references . إنها مجموعة من الكائنات التي تحدد المشاريع للرجوع إليها:

{
    "compilerOptions": {
        // The usual
    },
    "references": [
        { "path": "../src" }
    ]
}

يمكن أن تشير الخاصية path لكل مرجع إلى دليل يحتوي على ملف tsconfig.json ، أو إلى ملف التكوين نفسه (والذي قد يكون له أي اسم).

عندما تشير إلى مشروع ما ، تحدث أشياء جديدة:

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

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

composite

يجب أن يتم تمكين الإعداد الجديد composite للمشاريع المشار إليها.
هذا الإعداد ضروري لضمان أن TypeScript يمكنه تحديد مكان العثور على مخرجات المشروع المشار إليه بسرعة.
يؤدي تمكين علامة composite تغيير بعض الأشياء:

  • الإعداد rootDir ، إذا لم يتم تعيينه بشكل صريح ، يتم تعيينه افتراضيًا إلى الدليل الذي يحتوي على الملف tsconfig
  • يجب مطابقة جميع ملفات التنفيذ بنمط include أو مدرجة في مصفوفة files . إذا تم انتهاك هذا القيد ، فسيخبرك tsc بالملفات التي لم يتم تحديدها
  • يجب تشغيل declaration

declarationMaps

لقد أضفنا أيضًا دعمًا لخرائط مصدر الإعلان .
إذا قمت بتمكين --declarationMap ، فستتمكن من استخدام ميزات المحرر مثل "Go to Definition" وإعادة التسمية للتنقل بشفافية وتحرير التعليمات البرمجية عبر حدود المشروع في برامج التحرير المدعومة.

prepend مع outFile

يمكنك أيضًا تمكين الإعداد المسبق لمخرجات التبعية باستخدام الخيار prepend في المرجع:

   "references": [
       { "path": "../utils", "prepend": true }
   ]

سيشمل الإعداد المسبق للمشروع ناتج المشروع أعلى من ناتج المشروع الحالي.
يعمل هذا مع ملفات .js وملفات .d.ts ، كما سيتم إرسال ملفات خريطة المصدر بشكل صحيح.

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

  ^ ^ 
 /   \
B     C
 ^   ^
  \ /
   D

من المهم في هذا الموقف عدم الاعتماد مسبقًا على كل مرجع ، لأنك ستنتهي بنسختين من A بإخراج D - قد يؤدي هذا إلى نتائج غير متوقعة.

محاذير لمراجع المشروع

تحتوي مراجع المشروع على بعض المفاضلات التي يجب أن تكون على دراية بها.

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

بالإضافة إلى ذلك، للحفاظ على التوافق مع سير العمل البناء الحالية، tsc لن تبني تبعيات ما لم يحتج مع تلقائيا --build التبديل.
دعنا نتعلم المزيد عن --build .

وضع البناء لـ TypeScript

الميزة التي طال انتظارها هي عمليات الإنشاء الإضافية الذكية لمشاريع TypeScript.
في 3.0 يمكنك استخدام العلم --build مع tsc .
هذه نقطة دخول جديدة لـ tsc تتصرف كمنظم بناء أكثر من كونها مُترجمًا بسيطًا.

تشغيل tsc --build ( tsc -b للاختصار) سيؤدي إلى ما يلي:

  • البحث عن جميع المشاريع المشار إليها
  • اكتشف ما إذا كانت محدثة
  • إنشاء مشاريع قديمة بالترتيب الصحيح

يمكنك تزويد tsc -b بمسارات ملفات تكوين متعددة (مثل tsc -b src test ).
تمامًا مثل tsc -p ، فإن تحديد اسم ملف التكوين نفسه غير ضروري إذا كان اسمه tsconfig.json .

سطر الأوامر tsc -b

يمكنك تحديد أي عدد من ملفات التكوين:

 > tsc -b                                # Build the tsconfig.json in the current directory
 > tsc -b src                            # Build src/tsconfig.json
 > tsc -b foo/release.tsconfig.json bar  # Build foo/release.tsconfig.json and bar/tsconfig.json

لا تقلق بشأن طلب الملفات التي تمررها على سطر الأوامر - tsc سيعيد ترتيبها إذا لزم الأمر بحيث يتم دائمًا بناء التبعيات أولاً.

هناك أيضًا بعض العلامات الخاصة بـ tsc -b :

  • --verbose : طباعة التسجيل المطول لشرح ما يحدث (يمكن دمجه مع أي علم آخر)
  • --dry : يعرض ما يمكن فعله ولكن لا يقوم ببناء أي شيء فعليًا
  • --clean : حذف مخرجات المشاريع المحددة (يمكن دمجها مع --dry )
  • --force : تصرف كما لو أن جميع المشاريع قديمة
  • --watch : وضع المشاهدة (لا يجوز دمجه مع أي علم باستثناء --verbose )

تحفظات

عادة ، سينتج tsc مخرجات ( .js و .d.ts ) في وجود أخطاء بناء الجملة أو الكتابة ، ما لم يكن noEmitOnError قيد التشغيل.
سيكون القيام بذلك في نظام بناء تزايدي أمرًا سيئًا للغاية - إذا كان هناك خطأ جديد في إحدى التبعيات القديمة ، فستراه مرة واحدة فقط لأن الإنشاء اللاحق سيتخطى إنشاء المشروع المحدث الآن.
لهذا السبب ، يعمل tsc -b بفعالية كما لو أن noEmitOnError ممكّن لجميع المشاريع.

إذا قمت بإيداع أي مخرجات بناء ( .js ، .d.ts ، .d.ts.map ، إلخ.) ، فقد تحتاج إلى تشغيل بناء --force بعد بعض التحكم بالمصادر اعتمادًا على ما إذا كانت أداة التحكم بالمصدر تحافظ على خرائط الوقت بين النسخة المحلية والنسخة البعيدة.

msbuild

إذا كان لديك مشروع msbuild ، فيمكنك تشغيل تمكين وضع البناء عن طريق إضافة

    <TypeScriptBuildMode>true</TypeScriptBuildMode>

إلى ملف المشروع الخاص بك. سيؤدي ذلك إلى تمكين البناء الإضافي التلقائي بالإضافة إلى التنظيف.

لاحظ أنه كما هو الحال مع tsconfig.json / -p ، لن يتم احترام خصائص مشروع TypeScript الحالية - يجب إدارة جميع الإعدادات باستخدام ملف tsconfig الخاص بك.

قامت بعض الفرق بإعداد مهام سير عمل تستند إلى msbuild حيث يكون لملفات tsconfig نفس ترتيب الرسم البياني الضمني مثل المشاريع المُدارة التي يتم إقرانها بها.
إذا كان الحل الخاص بك على هذا النحو ، فيمكنك الاستمرار في استخدام msbuild مع tsc -p مع مراجع المشروع ؛ هذه قابلة للتشغيل المتبادل بشكل كامل.

إرشاد

الهيكل العام

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

من الممارسات الجيدة الأخرى أن يكون لديك ملف "حل" tsconfig.json يحتوي ببساطة على references لجميع مشاريع عقد الأوراق الخاصة بك.
هذا يمثل نقطة دخول بسيطة ؛ على سبيل المثال ، في TypeScript repo ، نقوم ببساطة بتشغيل tsc -b src لبناء جميع نقاط النهاية لأننا ندرج جميع المشاريع الفرعية في src/tsconfig.json
لاحظ أنه بدءًا من 3.0 ، لم يعد من الخطأ أن يكون لديك مصفوفة فارغة files إذا كان لديك على الأقل reference في ملف tsconfig.json .

يمكنك رؤية هذه الأنماط في مستودعات TypeScript - راجع src/tsconfig_base.json ، src/tsconfig.json ، و src/tsc/tsconfig.json كأمثلة رئيسية.

الهيكلة للوحدات النمطية النسبية

بشكل عام ، ليست هناك حاجة إلى الكثير لنقل الريبو باستخدام الوحدات النمطية النسبية.
ما عليك سوى وضع ملف tsconfig.json في كل دليل فرعي لمجلد رئيسي معين ، وإضافة reference s إلى ملفات التكوين هذه لمطابقة الطبقات المقصودة من البرنامج.
ستحتاج إما إلى تعيين outDir إلى مجلد فرعي واضح لمجلد الإخراج ، أو تعيين rootDir إلى الجذر المشترك لجميع مجلدات المشروع.

الهيكلة للملفات الخارجية

تخطيط التجميعات باستخدام outFile أكثر مرونة لأن المسارات النسبية لا تهم كثيرًا.
شيء واحد يجب أخذه في الاعتبار هو أنك تريد عمومًا عدم استخدام prepend حتى المشروع "الأخير" - سيؤدي ذلك إلى تحسين أوقات الإنشاء وتقليل مقدار الإدخال / الإخراج المطلوب في أي بنية معينة.
يعد مستودع TypeScript في حد ذاته مرجعًا جيدًا هنا - لدينا بعض مشروعات "المكتبات" وبعض مشروعات "نقطة النهاية" ؛ يتم الاحتفاظ بمشاريع "نقطة النهاية" صغيرة قدر الإمكان وتسحب فقط المكتبات التي يحتاجون إليها.

هيكلة monorepos

المهام: جرب أكثر واكتشف ذلك. يبدو أن لدى Rush و Lerna نماذج مختلفة تشير إلى أشياء مختلفة من جانبنا

أبحث أيضًا عن تعليقات على # 25164

RyanCavanaugh الكتابة لطيفة جدًا ، والميزة الممتازة ، سيكون من الرائع حقًا تجربتها ، esp. بعد أن أمضيت أيامًا في تنظيم مشروعنا الكبير في مشاريع فرعية مع مراجع ملفات التكوين.

لدي بضع ملاحظات:

  1. ما هو monorepo؟ سيكون من الجيد وصف حالة الاستخدام هذه أكثر قليلاً.
  2. في معظم الحالات (خاصة بالنسبة للمشروعات الكبيرة) ، هناك العديد من القطع الأثرية الإضافية التي تم إنشاؤها أثناء الإنشاء. في حالتنا هذه هي CSS و HTML وملفات الصور وما إلى ذلك عبر gulp. أتساءل كيف سيعتمد استخدام أدوات البناء هذه على هذه الطريقة الجديدة في القيام بالأشياء. لنفترض أنني أرغب في تشغيل الساعة ليس فقط على ملفات * .ts ، ولكن على جميع ملفاتنا الأخرى (الأنماط والترميز وما إلى ذلك). كيف يتم فعل ذلك؟ هل تحتاج إلى الجري ، لنقل أن gulp watch و tsc -b -w التوازي؟

vvs a monorepo عبارة عن مجموعة من حزم NPM تُدار عادةً بواسطة أداة مثل Rush أو Lerna

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

تضمين التغريدة أنا مهتم جدًا بإرشادات ليرنا :)

RyanCavanaugh يبدو هذا رائعًا ، فأنا أعمل حاليًا على تجربته مع lerna monorepo.

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

هذا رائع! أنا أعمل على ts-loader والمشاريع ذات الصلة. هل من المحتمل أن تكون التغييرات ضرورية لدعم هذا في المشاريع التي تستخدم TypeScript's LanguageServiceHost / WatchHost ؟

(راجع https://github.com/TypeStrong/ts-loader/blob/master/src/servicesHost.ts للحصول على مثال لما أعنيه.)

إذا كان الأمر كذلك ، فسيتم استلام جميع التوجيهات / العلاقات العامة بامتنان! في الواقع ، إذا كنت تريد اختبار هذا في عالم webpack ، فسيسعدني مساعدتك في دفع إصدار ts-loader الذي يدعم هذا.

بالطبع إذا كانت "تعمل فقط" فهذا أفضل: ابتسم:

عمل عظيم!

yortusEisenbergEffect لقد قمت بإعداد الريبو lerna عينة في https://github.com/RyanCavanaugh/learn-a مع README تحدد الخطوات التي اتخذت للحصول على عمل.

إذا فهمت بشكل صحيح ، فإن tsc -b X لن يفعل شيئًا إذا كان كل شيء (X وكل تبعياته وتبعياته المتعددة) محدثًا؟ هل تتساءل عما إذا كان هذا شيئًا يمكننا الحصول عليه حتى بدون علامة -b للمشاريع الفردية بدون مراجع؟ (ناقص التبعيات في هذه الحالة بالطبع)

هذا رائع جدا. أميل إلى استخدام تكوين Lerna مثل هذا (لفصل الريبو الأحادي حسب الوظيفة). أفترض أن هذا سيعمل أيضًا.

{
"lerna": "2.11.0"،
"الحزم": [
"الحزم / المكونات / " ،"الحزم / المكتبات / " ،
"الحزم / الأطر / " ،"الحزم / التطبيقات / " ،
"الحزم / الأدوات / *"
] ،
"الإصدار": "0.0.0"
}

إذن هذا متاح على typescript@next ؟

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

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

مثيرة للاهتمام حقا! حاليًا في شركتي ، نستخدم أداتي الخاصة المسماة

المشاريع لها تكوينات مختلفة مثل ؛ استهداف ECMA (es5 ، es6) ، أنواع (عقدة ، دعابة ، DOM ، إلخ) ، ينبعث (يستخدم البعض حزمة ويب والبعض الآخر يتم تجميعه إلى js نفسه). جميعهم يشتركون في شيء واحد ، وهو المكون الإضافي tslint ، والباقي يمكن أن يكون مختلفًا. تعمل أداتي أيضًا على تشغيل tslint بعد تجميع المشروع (لكل مشروع وتوقف إذا تمت إعادة ترجمة المشروع قبل انتهاء tslint).

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

لقد جربت وضع --build باستخدام lerna monorepo ، والذي يتكون حاليًا من 17 حزمة مترابطة. لقد استغرق الأمر بعض الوقت حتى يعمل كل شيء ، ولكن الآن كل شيء يعمل ، والقدرة على البناء بشكل تدريجي يعد تحسنًا كبيرًا بالنسبة لنا.

لقد واجهت بعض المشكلات التي أصفها أدناه. آمل أن تكون هذه تعليقات مفيدة لفريق TS وقد تساعد الآخرين في الحصول على وضع --build لمشاريعهم.

ملاحظات للوضع tsc --build

1. كاذبة "\قديم لأن ملف الإخراج '2.map' غير موجود "

لقد تلقيت هذه الرسالة لكل حزمة في كل بناء ، لذلك أصبح كل بناء إعادة بناء كاملة حتى عندما لم يتغير شيء. لقد لاحظت أن RyanCavanaugh قد أصلح هذا بالفعل في # 25281 ، لذلك لم تعد هناك مشكلة إذا قمت بالتحديث إلى 20180628 أو لاحقًا كل ليلة. تفترض المشكلات التالية أنك قمت بالتحديث إلى 20180628 ليلة على الأقل.

2. "\محدث بملفات .d.ts من تبعياته "عندما لا يكون كذلك

تحرير: تم الإبلاغ عنه في # 25337.

لإعادة إنتاج هذه المشكلة ، قم بإعداد نموذج ريبو RyanCavanaugh learn-a وفقًا لتعليماته . قم بتشغيل tsc -b packages --verbose لرؤية كل شيء يتم إنشاؤه في المرة الأولى. الآن قم بتغيير السطر 1 في pkg1/src/index.ts إلى import {} from "./foo"; واحفظه. قم بتشغيل tsc -b packages --verbose مرة أخرى. تم تخطي إصدار pkg2 ، على الرغم من تغيير pkg1 بطريقة تكسر مصدر pkg2 . يمكنك الآن رؤية تمايل أحمر في pkg2/src/index.ts . أنشئ مرة أخرى باستخدام tsc -b packages --force وسيظهر خطأ الإصدار. تفترض المشكلات التالية البناء باستخدام --force للتغلب على هذا.

3. تم إنشاء ملفات .d.ts مما تسبب في أخطاء إنشاء "المعرف المكرر" في الحزم النهائية

تحرير: تم الإبلاغ عنه في # 25338.

لإعادة إنتاج هذه المشكلة ، قم بإعداد نموذج ريبو RyanCavanaugh learn-a وفقًا لتعليماته . الآن قم بتشغيل lerna add @types/node لإضافة كتابة Node.js إلى جميع الحزم الثلاثة. قم بتشغيل tsc -b packages --force لتأكيد أنه لا يزال يبني جيدًا. أضف الآن الكود التالي إلى pkg1/src/index.ts :

// CASE1 - no build errors in pkg1, but 'duplicate identifier' build errors in pkg2
// import {parse} from 'url';
// export const bar = () => parse('bar');

// CASE2 - no build errors in pkg1 or in downstream packages
// import {parse, UrlWithStringQuery} from 'url';
// export const bar = (): UrlWithStringQuery => parse('bar');

// CASE3 - no build errors in pkg1 or in downstream packages
// export declare const bar: () => import("url").UrlWithStringQuery;

// CASE4 - no build errors in pkg1, but 'duplicate identifier' build errors in pkg2
// import {parse} from 'url';
// type UrlWithStringQuery = import("url").UrlWithStringQuery;
// export const bar = (): UrlWithStringQuery => parse('bar');

قم بإلغاء التعليق على حالة واحدة في كل مرة وقم بتشغيل tsc -b packages --force . تتسبب الحالتان 1 و 4 في حدوث طوفان من أخطاء الإنشاء في pkg2 . في الحالتين 2 و 3 ، لا توجد أخطاء في البناء. يبدو أن الاختلاف المهم مع الحالتين 1 و 4 هو السطر الأول في pkg1/lib/index.d.ts إنشاؤه:

/// <reference path="../node_modules/@types/node/index.d.ts" />

الحالتان 2 و 3 لا تولدان هذا الخط. عندما يتم إنشاء pkg2 في الحالتين 1 و 4 ، فإنه يشتمل على نسختين متطابقتين من إعلانات @types/node بمسارات مختلفة ، وهذا يسبب أخطاء "المعرف المكرر".

ربما يكون هذا حسب التصميم لأن الحالتين 2 و 3 تعملان. ومع ذلك يبدو محيرا جدا. لا توجد أخطاء أو تحذيرات في الإصدار في pkg1 لأي من هذه الحالات الأربع ، لكن سلوك الإنشاء المتلقين للمعلومات حساس جدًا للنمط الدقيق للإعلانات المصدرة. أعتقد أنه إما (أ) pkg1 يجب أن يكون خطأ في الحالتين 1 و 4 ، أو (ب) يجب أن يكون لجميع الحالات الأربع نفس سلوك الإنشاء النهائي ، أو (ج) يجب أن يكون هناك بعض التوجيه الواضح من فريق TS بشأن كيفية كتابة التصريحات لتجنب هذه المشكلة.

4. مشاكل مع import الأنواع في لدت .d.ts الملفات عند استخدام مساحات الغزل

عند محاولة تشغيل وضع الإنشاء مع 17 حزمة monorepo الخاصة بنا ، عملت من خلال عدد من أخطاء الإنشاء التي تسببها المسارات النسبية في أنواع import في ملفات .d.ts إنشاؤها. لقد توصلت أخيرًا إلى أن المشكلة تتعلق برفع الوحدة. أي عند استخدام مساحات عمل الغزل ، يتم رفع جميع الوحدات النمطية المثبتة إلى الدليل monorepo-root node_modules ، بما في ذلك الارتباطات الرمزية لجميع الحزم في monorepo. لقد غيرت monorepo لاستخدام الخاصية packages في lerna.json ، مما يتسبب في استخدام lerna لوغاريتم التمهيد غير الرافع الخاص بها ، وهذا حل المشكلة. إنه نهج أفضل / أكثر أمانًا على أي حال ، على الرغم من أنه أبطأ.

لست متأكدًا مما إذا كان TS يعتزم دعم إعدادات رفع الوحدة النمطية ، لذلك لم أطور نسخة عن المشكلات التي واجهتها ، لكن يمكنني محاولة إنشاء واحدة إذا كان هناك اهتمام. أعتقد أن المشكلة قد تكون أن بعض الإصدارات تحصل على نفس النوع عبر دليل المستوى الأعلى packages (وفقًا لإعدادات tsconfig) ودليل المستوى الأعلى node_modules (وفقًا لـ import في ملفات .d.ts إنشاؤها). يعمل هذا أحيانًا بسبب الكتابة الهيكلية ، لكنه يفشل في أشياء مثل الرموز الفريدة المصدرة.

5. التكوين المتكرر

يتطلب إعداد monorepo لاستخدام lerna وضع شيء مثل "packages": ["packages/*"] في lerna.json . يعمل Lerna على تحديد قائمة الحزم الدقيقة عن طريق توسيع globstars ، ثم يعمل على رسم بياني التبعية الدقيق من خلال النظر في التبعيات المعلنة في كل حزمة package.json . يمكنك إضافة وإزالة الحزم والتبعيات حسب الرغبة ، و lerna يستمر دون الحاجة إلى لمس التكوين الخاص به.

وضع TypeScript --build يتضمن احتفالًا أكثر قليلاً. لم يتم التعرف على أنماط الكرة الأرضية ، لذلك يجب إدراج جميع الحزم وصيانتها بشكل صريح (على سبيل المثال في packages/tsconfig.json ) في نموذج الريبو الخاص بـ RyanCavanaugh learn-a . لا ينظر وضع البناء إلى تبعيات package.json ، لذلك يجب أن تحتفظ كل حزمة بقائمة الحزم الأخرى التي تعتمد عليها في ملفها package.json (أقل من "dependencies" ) وكذلك إنه ملف tsconfig.json (أقل من "references" ).

هذا إزعاج بسيط ، لكني أدرجه هنا لأنني وجدت أن الصمغ الملحوظ ملحوظًا مقارنة بنهج lerna's .

6. تعطل tsc مع الإضافات الشاملة للوحدة

تحرير: تم الإبلاغ عنه في # 25339.

لإعادة إنتاج هذه المشكلة ، قم بإعداد نموذج ريبو RyanCavanaugh learn-a وفقًا لتعليماته . الآن قم بتشغيل lerna add @types/multer لإضافة كتابة multer إلى الحزم الثلاثة. قم بتشغيل tsc -b packages --force لتأكيد أنه لا يزال يبني جيدًا. أضف الآن السطر التالي إلى pkg1/src/index.ts :

export {Options} from 'multer';

قم بتشغيل tsc -b packages --force مرة أخرى. المترجم يتعطل بسبب تأكيد منتهك. نظرت بإيجاز إلى تتبع المكدس والتأكيد ، ويبدو أن هذا له علاقة بالتكبير العالمي لمساحة الاسم Express .

شكرا @ yortus على ردود الفعل. الاعتماد نقدر ذلك. لـ 3 ، أعتقد أنه https://github.com/Microsoft/TypeScript/issues/25278.

بالنسبة لـ 4 ، لست على دراية برفع الوحدة كمفهوم. هل يمكنك تفصيل و / أو مشاركة تعبير؟

mhegazy كثير من الذين يستخدمون lerna والغزل يستخدمون مساحات العمل (بما فيهم أنا). مزيد من المعلومات هنا: https://yarnpkg.com/lang/en/docs/workspaces/

أنا أستخدم حاليًا مساحات عمل الغزل ، lerna ، tsconfigs الموسعة حيث يعلن tsconfig الأساسي أن paths مشترك لجميع الحزم مع وحدة الرفع الموجودة تحت root/node_modules . عندما أسمع yarn و monorepo ، أعتقد أن workspaces لأن هذا هو الهدف من الميزة - لتسهيل الاستخدام وتقليل التكرار. كنت أتوقع أن يؤدي هذا التغيير ببساطة إلى إزالة paths قمت بإعلانه في tsconfig الأساسي الخاص بي.

فيما يلي عينة من الجذر monorepo tsconfig (إذا كان مفيدًا):

{
  "extends": "./packages/build/tsconfig.base.json",
  "compilerOptions": {
    "baseUrl": "./packages",
    "paths": {
      "@alienfast/build/*": ["./build/src/*"],
      "@alienfast/common-node/*": ["./common-node/src/*"],
      "@alienfast/common/*": ["./common/src/*"],
      "@alienfast/concepts/*": ["./concepts/src/*"],
      "@alienfast/faas/*": ["./faas/src/*"],
      "@alienfast/math/*": ["./math/src/*"],
      "@alienfast/notifications/*": ["./notifications/src/*"],
      "@alienfast/ui/*": ["./ui/src/*"],
      "@alienfast/build": ["./build/src"],
      "@alienfast/common-node": ["./common-node/src"],
      "@alienfast/common": ["./common/src"],
      "@alienfast/concepts": ["./concepts/src"],
      "@alienfast/faas": ["./faas/src"],
      "@alienfast/math": ["./math/src"],
      "@alienfast/notifications": ["./notifications/src"],
      "@alienfast/ui": ["./ui/src"],
    }
  },
  "include": ["./typings/**/*", "./packages/*/src/**/*"],
  "exclude": ["node_modules", "./packages/*/node_modules"]
}

سآخذ لقطة للتشعب لعينة:
https://github.com/RyanCavanaugh/learn-a

في ما يلي بيان علاقات عامة غير RyanCavanaugh مع مساحات عمل الغزل:
https://github.com/RyanCavanaugh/learn-a/pull/3/files

استخدمنا أيضًا وحدة الرفع في Jupyterlab ، مع lerna والغزل. يسمح لنا بمشاركة التبعيات المثبتة لدينا بين جميع حزمنا ، بحيث لا توجد إلا مرة واحدة في نظام الملفات ، في مشروع الجذر.

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

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

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

لقد أضفت عنصرًا سادسًا إلى ملاحظاتي السابقة . أعطال tsc في السيناريو الموصوف هناك.

mhegazy لست متأكدًا من ارتباط العنصر 3 بـ # 25278. يصف # 25278 إصدار إعلان غير صالح. كانت ملفات التصريح التي تم إنشاؤها صالحة من الناحية التركيبية والمعنوية ، ولكنها تسببت في إنشاء مشاريع نهائية بنسختين من أنواع العقدة ، مما أدى إلى حدوث أخطاء في "المعرف المكرر".

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

بالمناسبة ، هناك جانب سلبي لهذا النموذج ، وهو أنه يؤدي إلى "التبعيات الوهمية" حيث يمكن للمشروع استيراد تبعية لم يتم الإعلان عنها صراحة في ملف package.json الخاص به. عندما تنشر مكتبتك ، يمكن أن يتسبب ذلك في مشكلة مثل (1) تثبيت إصدار مختلف من التبعية عما تم اختباره / توقعه ، أو (2) فقدان التبعية تمامًا لأنه تم رفعها من مشروع غير ذي صلة لم يتم تثبيته في هذا السياق. لدى كل من PNPM و Rush خيارات معمارية تهدف إلى الحماية من التبعيات الوهمية.

لدي سؤال عام حول tsc --build : هل يسعى برنامج التحويل البرمجي TypeScript إلى تولي دور تنسيق الإنشاء للمشاريع في monorepo؟ عادةً ما تحتوي سلسلة الأدوات على مجموعة كاملة من المهام ، مثل:

  • المعالجة
  • توليد سلاسل مترجمة
  • تحويل الأصول إلى JavaScript (css ، الصور ، إلخ)
  • التحويل البرمجي (فحص النوع / التحويل)
  • نشمر عن ملفات .js (مثل webpack)
  • نشمر عن ملفات .d.ts (مثل API Extractor)
  • المعالجة اللاحقة بما في ذلك اختبارات الوحدة وإنشاء الوثائق

عادةً ما يقوم نظام مثل Gulp أو Webpack بإدارة خط الأنابيب هذا ، ويكون المترجم مجرد خطوة واحدة في منتصف السلسلة. أحيانًا تقوم أداة ثانوية أيضًا بتشغيل الإنشاء بطريقة أخرى ، على سبيل المثال Jest + ts-jest مقابل jest --watch .

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

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

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

pgonzal صحيح ، هناك العديد من الأجزاء غير التابعة لـ tsc لبناء عالم حقيقي monorepo. بالنسبة إلى lerna monorepo ، اتبعت النهج التالي:

  • تحدد كل حزمة في monorepo اختياريًا برنامجًا نصيًا prebuild و / أو برنامج نصي postbuild في package.json . هذه تحتوي على جوانب غير tsc للبناء.
  • في Monorepo package.json ، توجد هذه البرامج النصية:
    "prebuild": "lerna run prebuild", "build": "tsc --build monorepo.tsconfig.json --verbose", "postbuild": "lerna run postbuild",
  • هذا كل شيء. يؤدي تشغيل yarn build على مستوى monorepo إلى تشغيل البرامج النصية prebuild لكل حزمة تحددها ، ثم يتم تشغيل الخطوة tsc --build ، ثم يتم تشغيل كل postbuild نصوص. (وفقًا للاتفاقية في كل من npm والغزل ، فإن تنفيذ npm run foo هو تقريبًا نفس npm run prefoo && npm run foo && npm run postfoo .)

كيف تتعامل مع jest --watch أو webpack-dev-server ؟ على سبيل المثال ، عند تعديل ملف مصدر ، هل يتم تشغيل خطوات الإنشاء المسبق / ما بعد البناء مرة أخرى؟

هل هذا له أي آثار على ts-node ومهام سير العمل ذات الصلة؟ تعمل بعض التطبيقات المساعدة لدينا "مباشرة" من TypeScript ، مثل "start": "ts-node ./src/app.ts" أو "start:debug": "node -r ts-node/register --inspect-brk ./src/app.ts" .

تم الإبلاغ عن مشكلة أخرى في وضع البناء في # 25355.

شكرا لجميع ردود الفعل والتحقيقات الرائعة حتى الآن. إنني أقدر حقًا كل من استغرق وقتًا لتجربة الأشياء وركل الإطارات.

yortus re https://github.com/Microsoft/TypeScript/issues/3469#issuecomment -400439520

كتابة رائعة ، شكرًا مرة أخرى على تقديم هذا. مشاكلك بالترتيب -

  1. مثبت
  2. PR up at # 25370
  3. مناقشة المشكلة المسجلة - ليس من الواضح على الفور ما هو الإصلاح الصحيح ، لكننا سنفعل شيئًا
  4. التحقيق (أدناه)
  5. تسجيل # 25376
  6. لا علاقة لها من الناحية الفنية بـ --build AFAICT. هذا تأكيد جديد أضفناه مؤخرًا ؛ تحقيق ناثان

crosskevin 🎉 للعلاقات العامة على الريبو learn-a ! سأقوم بدمج ذلك في فرع حتى نتمكن من المقارنة والتباين بشكل أفضل.

pgonzal re https://github.com/Microsoft/TypeScript/issues/3469#issuecomment -401577442

لدي سؤال عام حول tsc --build: هل يسعى برنامج التحويل البرمجي TypeScript إلى تولي دور تنسيق الإنشاء للمشاريع في monorepo؟

سؤال رائع أريد أن أجيب على هذا السؤال بوضوح شديد: بالتأكيد لا .

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

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

borekb re https://github.com/Microsoft/TypeScript/issues/3469#issuecomment -401593804

هل هذا له أي آثار على عقدة ts وتدفقات العمل ذات الصلة؟ تعمل بعض التطبيقات المساعدة لدينا "مباشرة" من TypeScript

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

كان لدى EisenbergEffect بعض الأسئلة في learn-a repo حول إعادة تسمية المشروع المشترك وميزات خدمة اللغة الأخرى. السؤال الكبير المفتوح هنا هو فقط ما إذا كنا سنكون قادرين على الحصول على هذه الميزة في حالة قابلة للاستخدام لمدة 3.0 أم لا. إذا كان الأمر كذلك ، فإن إعادة تسمية المشروع عبر "ستعمل فقط" ، مع مراعاة التحذير بأنه من المستحيل بالنسبة لنا العثور بشكل قاطع على جميع المشاريع النهائية وتحديثها - سيكون هذا "أفضل جهد" استنادًا إلى بعض الأساليب البحثية للبحث عن أخرى المشاريع.

إذا لم نعتقد أن إعادة تسمية المشاريع المشتركة مستقرة بشكل مقبول + مكتملة لـ 3.0 ، فمن المحتمل أن نحظر عمليات إعادة التسمية فقط عندما يكون الرمز المعاد تسميته في ملف الإخراج .d.ts لمشروع آخر - مما يسمح لك بالقيام بذلك سيكون محير للغاية لأن ملف .d.ts سيتم تحديثه في بناء لاحق لمشروع المنبع بعد تعديل مشروع المنبع ، مما يعني أنه يمكن بسهولة أن تمر أيام بين وقت إجراء إعادة تسمية محلية وعندما تدرك أن رمز الإعلان لم يتم تحديثه بالفعل.

بالنسبة إلى ميزات مثل Go to Definition ، تعمل هذه الميزات اليوم في VS Code وستعمل خارج الصندوق في الإصدارات المستقبلية من Visual Studio. تتطلب جميع هذه الميزات تمكين ملفات d.ts.map. (قم بتشغيل declarationMap ). هناك بعض العمل لكل ميزة لإضاءة هذا الأمر ، لذلك إذا رأيت شيئًا لا يعمل كما هو متوقع ، فقم بتسجيل خطأ لأننا ربما فاتنا بعض الحالات.

افتح المشكلات التي أتتبعها في هذه المرحلة:

  • إعادة تسمية المشروع المشترك - يتم تنفيذ @ andy-ms
  • تحتاج إلى تحليل إعدادات الوحدات المرفوعة وفهم آثارها - علي
  • يجب أن يكون هناك إصدار من نموذج learn-a repo يستخدم yarn ، وآخر يستخدم pnpm ، وآخر يستخدم واحدًا من تلك الموجودة في وضع الرافعة

أسئلة مفتوحة

  • هل يجب أن نطبق المنطق لقراءة package.json s لاستنتاج مراجع المشروع؟ تسجيل # 25376
  • هل يجب تفعيل إصدار .d.ts.map بشكل ضمني لمشاريع composite ؟

RyanCavanaugh للإضافة إلى

افتح المشاكل التي أتتبعها في هذه المرحلة

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

آسف على سؤال غبي ، لأنه تم التحقق منه في خارطة الطريق ، كيف يمكنني تمكين هذه الميزة؟

@ aleksey-bykov يمكنك استخدامه في الكتابة المطبوعة @ next.

لقد جربت هذا للتو على monorepo في مساحة عمل الغزل لدينا وهي تعمل بشكل جيد.

أحد الأشياء التي لاحظتها هو أن tsc --build --watch عن أخطاء ولكن بعد ذلك لم ينتج عنه أي شيء ليقول إن الإصدار قد تم إصلاحه الآن. بدأ وضع المشاهدة القياسي tsc في 2.9 بإعطاء عدد أخطاء ومن الجيد أن ترى صفرًا هناك حتى تعرف أن المبنى قد اكتمل.

لدي مجلد مليء بـ * .d.ts ولا شيء آخر ما يفترض أن أفعله حيال ذلك:

  • اجعله مشروعًا وقم بالإشارة إليه (حاول ، لم ينجح)
  • استخدام "تضمين" لذلك

timfish أن التعليقات تتطابق مع بعض التعليقات الأخرى التي سمعتها ؛ مسجل # 25562

@ aleksey-bykov يجب أن يساعد https://github.com/Microsoft/TypeScript/issues/3469#issuecomment -400439520 في شرح بعض المفاهيم

RyanCavanaugh يبدو أن إحالة المشروع تعمل فقط مع حل Commonjs ووحدة العقدة ، أليس كذلك؟

في مثالك:

import * as p1 from "@ryancavanaugh/pkg1";
import * as p2 from "@ryancavanaugh/pkg2";

p1.fn();
p2.fn4();
  1. ما هي الوحدة النمطية @ryancavanaugh ، هل لها علاقة بكيفية حل TS للوحدات النمطية؟
  2. هل من المفترض أن يعمل هذا المثال مع AMD (دقة الوحدة الكلاسيكية)؟
  3. هل مطلوب outFile لإيجاد التعريفات؟
  4. أين من المفترض أن تكون ملفات d.ts من أجل الرجوع إلى المشروع للعثور عليها (هل يمكنني الاستمرار في استخدام outDir؟ هل سيجدها TS هناك؟)

لدي مشروعان بسيطان essentials و common والأشياء المشتركة لا يمكنها حل الأشياء المجمعة في الأساسيات:

image

@ aleksey-bykov

  1. إنه مجرد اسم وحدة محددة النطاق ، يتم حله بموجب خوارزمية دقة وحدة العقدة المعتادة
  2. يمكنك استخدام مراجع المشروع مع أي نظام وحدة نمطية بما في ذلك النظام الكلاسيكي ، ولكن أسماء الأمثلة (الوحدات النمطية) ليست سهلة الاستخدام خارج العقدة
  3. لا
  4. يبحث TypeScript عن ملفات .d.ts لتكون في المكان الذي ينشئها فيه المشروع المشار إليه

إذا كان لديك نموذج ريبو أو شيء ما يمكنني تشخيص سبب حصولك على هذا الخطأ

تضمين التغريدة
example.zip

RyanCavanaugh ، يبدو أيضًا أن tsc --build --watch لا ينتج في البداية أي ملفات حتى يرى تعديلًا لملف المصدر.

الخيط طويل جدًا (في كل من الزمان والمكان) ؛ دعنا نبدأ المناقشة في العدد المحظوظ رقم 100 * 2 ^ 8: # 25600

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