تجميع مكتبة المكونات الزاوي كمكونات ويب

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

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

صورة

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

إعداد وحدة


أولاً ، دعنا نتذكر الشكل الذي يجب أن تبدو عليه الوحدة لتجميع العناصر الزاوية.

@NgModule({ imports: [BrowserModule], entryComponents: [SomeComponent], }) export class AppModule { constructor(readonly injector: Injector) { const ngElement = createCustomElement(SomeComponent, { injector, }); customElements.define('some-component', ngElement); } ngDoBootstrap() {} } 

نحتاج:

  1. أضف إلى المدخل المكون المكون الذي نخطط لإنشاء عنصر الزاوي ، واستيراد الوحدات اللازمة للمكون.
  2. إنشاء عنصر الزاوي باستخدام createCustomElement وحاقن.
  3. قم بتعريف أحد مكونات الويب في customElements لمتصفحك.
  4. تجاوز طريقة ngDoBootstrap لإفراغها.

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

 export abstract class MyElementModule { constructor(injector: Injector, component: InstanceType<any>, name: string) { const ngElement = createCustomElement(component, { injector, }); customElements.define(`${MY_PREFIX}-${name}`, ngElement); } ngDoBootstrap() {} } 

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

 @NgModule({ imports: [BrowserModule, MyButtonModule], entryComponents: [MyButtonComponent], }) export class ButtonModule extends MyElementModule { constructor(injector: Injector) { super(injector, MyButtonComponent, 'button'); } } 

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

الوحدة جاهزة للتجميع وستقدم لنا مجموعة من ملفات JS التي يمكن طيها في مكون ويب منفصل. وبهذه الطريقة يمكننا إنشاء عدة وحدات وتدوير تجميع مكونات الويب منها.

تجميع بعض المكونات


نحتاج الآن إلى إعداد عملية bootstrap للوحدات النمطية الناتجة. الأهم من ذلك كله أنني أحب فكرة وضع هذا المنطق في ملف منفصل قابل للتنفيذ ، والذي سيكون مسؤولاً عن تجميع وحدة نمطية معينة.

هيكل العناصر يذهب شيء مثل هذا:

صورة

سيبدو ملف الترجمة المنفصل في الإصدار الأبسط كما يلي:

 enableProdMode(); platformBrowserDynamic() .bootstrapModule(ButtonModule) .catch(err => console.error(err)); 

سيساعد هذا النهج على تجاوز الوحدات المعدة بسهولة والحفاظ على هيكل المشروع مع عناصر واضحة وبسيطة.

في إعدادات بناء angular.json ، نحدد مسار الملف الذي تم جمعه إلى مجلد مؤقت معين داخل dist:

 "outputPath": "projects/elements/dist/tmp" 

سيكون هناك مجموعة من ملفات الإخراج بعد تجميع الوحدة.

للتجميع نفسه ، استخدم أمر build المعتاد في الزاوي - CLI:

 ng run elements:build:production --main='projects/elements/src/${project}/${component}/compile.ts' 

سيكون العنصر المنفصل هو المنتج النهائي ، لذلك نقوم بتشغيل إشارات الإنتاج باستخدام تجميع Ahead-of-Time ، وبعد ذلك نستبدل المسار إلى الملف القابل للتنفيذ ، والذي يتكون من المشروع واسم المكون.

سنقوم الآن بجمع النتيجة في ملف منفصل ، والذي سيكون الحزمة النهائية لمكون الويب المنفصل. للقيام بذلك ، استخدم القط المعتاد:

 cat dist/tmp/runtime.js dist/tmp/main.js > dist/tmp/my-${component}.js 

من المهم أن نلاحظ هنا أننا لا نضع ملف polyfills.js في حزمة كل مكون ، لأننا نحصل على ازدواجية إذا استخدمنا عدة مكونات في نفس الصفحة في المستقبل. بالطبع ، يجب عليك تعطيل الخيار outputHashing في angular.json.

سننقل الحزمة الناتجة من مجلد مؤقت إلى مجلد لتخزين المكونات. على سبيل المثال ، مثل هذا:

 cp dist/tmp/my-${component}.js dist/components/ 

يبقى فقط وضع كل شيء معًا - والنص البرمجي للتجميع جاهز:

 // compileComponents.js projects.forEach(project => { const components = fs.readdirSync(`src/${project}`); components.forEach(component => compileComponent(project, component)); }); function compileComponent(project, component) { const buildJsFiles = `ng run elements:build:production --aot --main='projects/elements/src/${project}/${component}/compile.ts'`; const bundleIntoSingleFile = `cat dist/tmp/runtime.js dist/tmp/main.js > dist/tmp/my-${component}.js`; const copyBundledComponent = `cp dist/tmp/my-${component}.js dist/components/`; execSync(`${buildJsFiles} && ${bundleIntoSingleFile} && ${copyBundledComponent}`); } 

الآن لدينا أب أنيق مع مجموعة من مكونات الويب:

صورة

قم بتوصيل المكونات بصفحة عادية


يمكن إدراج مكونات الويب المجمعة الخاصة بنا بشكل مستقل في الصفحة ، وربط حزم JS الخاصة بهم حسب الحاجة:

 <my-elements-input id="input"> </<my-elements-input> <script src="my-input.js"></script> 

حتى لا نقوم بسحب المنطقة بأكملها. js مع كل مكون ، فإننا نقوم بتوصيله مرة واحدة في بداية المستند:

 <script src="zone.min.js"></script> 

يتم عرض المكون على الصفحة ، وكل شيء على ما يرام.

ودعنا نضيف زر:

 <my-elements-button size="l" onclick="onClick()"></my-elements-button> <script src="my-button.js"></script> 

نطلق الصفحة و ...

صورة

أوه ، إنه محطم!

إذا نظرنا إلى الحزمة ، نجد هناك مثل هذا الخط غير الواضح:

 window.webpackJsonp=window.webpackJsonp||[] 

صورة

نافذة تصحيحات Webpack ، حتى لا تتكرر عملية تحميل نفس الوحدات. اتضح أن المكون الأول فقط الذي تمت إضافته إلى الصفحة يمكنه إضافة نفسه إلى customElements.

لحل هذه المشكلة ، نحتاج إلى استخدام custom-webpack:

  1. أضف custom-webpack إلى المشروع مع العناصر:

    ng add @angular-builders/custom-webpack --project=elements

  2. تكوين angular.json:

     "builder": "@angular-builders/custom-webpack:browser", "options": { "customWebpackConfig": { "path": "./projects/elements/elements-webpack.config.js" }, ... 

  3. قم بإنشاء ملف تكوين webpack مخصص:

     module.exports = { output: { jsonpFunction: 'myElements-' + uuidv1(), library: 'elements', }, }; 

    في ذلك ، نحن بحاجة إلى إنشاء معرف فريد لكل تجميع بأي طريقة مريحة. لقد استفدت من uuid.

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

جلب الجمال


تستخدم مكوناتنا متغيرات CSS العالمية التي تحدد سمة اللون وحجم المكونات.

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

 // compileHelpers.js compileMainTheme(); function compileMainTheme() { const pathFrom = `../../main-project/styles/themes`; const pathTo = `dist/helpers`; execSync( `lessc ${pathFrom}/theme-default-vars.less ${pathTo}/main-theme.css`,; ); } 

نحن نستخدم أقل من ذلك ، لذلك فقط تجميع المتغيرات lessc لدينا ووضع الملف الناتج في مجلد المساعدين.

يتيح لك هذا النهج التحكم في تصميم جميع مكونات الويب في الصفحة دون الحاجة إلى إعادة ترجمة هذه العناصر.

النصي النهائي


في الواقع ، يمكن اختزال العملية الكاملة لتجميع العناصر الموضحة أعلاه إلى مجموعة من الإجراءات:

 #!/bin/sh rm -r -f dist/ && mkdir -p dist/components && node compileElements.js && node compileHelpers.js && rm -r -f dist/tmp 

يبقى فقط استدعاء هذا البرنامج النصي من الحزمة الرئيسية. json لتقليل العملية الكاملة لتجميع المكونات الزاوي الفعلي لإطلاق أمر واحد.

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

في المجموع


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

يمكن لأي مطور إضافة مكون إلى مجموعة من العناصر وتجميعها في مجموعة من حزم JS المنفصلة لمكونات الويب دون الخوض في تفاصيل العمل مع Angular Elements.

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


All Articles