نبدأ من البداية
إذا كانت الذاكرة تخدمني بشكل صحيح ، فمنذ الإصدار 6 بزاوية ، أصبح من الممكن إنشاء أنواع مختلفة من المشاريع في مساحة عمل واحدة: التطبيق والمكتبة.
حتى هذه النقطة ، من المرجح أن الأشخاص الذين أرادوا إنشاء مكتبة مكونات استخدموا حزمة ng-packagr الممتازة والمفيدة ، والتي ساعدت في إنشاء الحزمة بالتنسيق المقبول للزاوي. في الواقع ، قمت بإنشاء المكتبة السابقة باستخدام هذه الأداة. الآن قام الفريق الزاوي بتضمين ng-packagr في الزاوي وخطط إضافية مضافة لإنشاء المكتبات وتوسيعها ، وتوسيع تنسيق الزاوي. json وإضافة المزيد من وسائل الراحة. دعنا الآن ننتقل من ng new to npm install - من إنشاء مكتبة فارغة إلى نشرها واستيرادها إلى مشروع تابع لجهة أخرى.
يتم إنشاء مساحة العمل كالمعتاد
ng new test-app 
سيتم إنشاء مساحة العمل والتطبيق المشروع ، نلقي نظرة على angular.json
 { ... "projects": { "test-app": { ... "sourceRoot": "src", "projectType": "application", "prefix": "app" ... } ... } ... } 
الآن إضافة مشروع المكتبة
 ng generate library test-lib --prefix=tl 
سنضيف مفتاح - الإصلاح للإشارة إلى أن المكونات والتوجيهات ستستخدم بادئة tl ، أي أن علامات المكونات ستبدو
 <tl-component-name></tl-component-name> 
دعونا نرى الآن في angular.json ، لقد أضفنا مشروع جديد
 { ... "projects": { "test-app": { "root": "", "sourceRoot": "src", "projectType": "application", "prefix": "app" ... }, ... "test-lib": { "root": "projects/test-lib", "sourceRoot": "projects/test-lib/src", "projectType": "library", "prefix": "tl" } ... } ... } 
ظهرت البنية التالية في دليل المشروع
 - projects - test-lib ng-package.json package.json - src public-api.ts - lib test-lib.component.ts test-lib.module.ts test-lib.service.ts 
أيضا ، في tsconfig.json هناك إضافة في قسم المسارات
 "paths": { "test-lib": [ "dist/test-lib" ], "test-lib/*": [ "dist/test-lib/*" ] } 
الآن ، إذا قمت بتشغيل التطبيق ،
 ng serve 
ثم سوف نرى قالب تطبيق الزاوي العمل القياسية
إنشاء وظائف المكتبة
لنقم بإنشاء مكتبة مع خدمة وتوجيه ومكون. سنضع الخدمة والتوجيه في وحدات مختلفة. دعنا ننتقل إلى دليل المشروعات / test-lib / src / lib وحذف test-lib. *. Ts ، أيضًا احذف محتويات المشروعات / test-lib / src / public-api.ts.
دعنا ننتقل إلى المشاريع / test-lib / src / lib وإنشاء وحدات ، توجيه ، خدمة ومكون
 ng g module list ng g module border ng g service list /*  list*/ ng g component list /*  border*/ ng g directive border 
ملء المكون والخدمة والتوجيه مع المنطق. سيعرض المكون قائمة بالصفوف المرسلة إلى الإدخال. التوجيه هو إضافة إطار أحمر ، ستضيف الخدمة الطابع الزمني الحالي إلى Observable كل ثانية.
خدمة
  import {Injectable} from '@angular/core'; import {Observable, Subject} from 'rxjs'; @Injectable({ providedIn: 'root' }) export class ListService { timer: any; private list$: Subject<string> = new Subject<string>(); list: Observable<string> = this.list$.asObservable(); constructor() { this.timer = setInterval(this.nextItem.bind(this), 1000); } nextItem() { const now = new Date(); const currentTime = now.getTime().toString(); this.list$.next(currentTime); } } 
قائمة المكونات والوحدة
  import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {ListComponent} from './list/list.component'; @NgModule({ declarations: [ ListComponent ], exports: [ ListComponent ], imports: [ CommonModule ] }) export class ListModule { }  @Component({ selector: 'tl-list', template: ` <ul> <li *ngFor="let item of list">{{item}}</li> </ul>`, styleUrls: ['./list.component.css'], changeDetection: ChangeDetectionStrategy.OnPush }) export class ListComponent implements OnInit { @Input() list: string[]; constructor() { } ngOnInit() { } } 
إطار
  import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {BorderDirective} from './border.directive'; @NgModule({ declarations: [ BorderDirective ], exports: [ BorderDirective ], imports: [ CommonModule ] }) export class BorderModule { }  import {Directive, ElementRef, OnInit} from '@angular/core'; @Directive({ selector: '[tlBorder]' }) export class BorderDirective implements OnInit { private element$: HTMLElement; constructor(private elementRef$: ElementRef) { this.element$ = elementRef$.nativeElement; } ngOnInit() { this.element$.style.border = 'solid 1px red'; } } 
! هذا مهم. عند إنشاء المكونات والمكتبات ، لا يُنشئ cli عملية تصدير ، لذا تأكد من إضافة المكونات والتوجيهات التي يجب أن تكون متاحة في قسم الصادرات في الوحدات النمطية.
علاوة على ذلك ، بحيث تتوفر فصول المستقبل من المكتبة ، سنضيف بعض الأكواد إلى api.ts العامة
 export * from './lib/list.service'; export * from './lib/border/border.module'; export * from './lib/border/border.directive'; export * from './lib/list/list.module'; export * from './lib/list/list/list.component'; 
توصيل مكتبة في تطبيق اختبار
دعونا تجميع مشروع المكتبة
 ng build test-lib --watch 
بعد ذلك في app.module سنقوم باستيراد الوحدات مع المكون والتوجيه وإضافة المنطق
  import {BrowserModule} from '@angular/platform-browser'; import {NgModule} from '@angular/core'; import {AppRoutingModule} from './app-routing.module'; import {AppComponent} from './app.component'; import {ListModule} from 'test-lib'; import {BorderModule} from 'test-lib';  @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, ListModule, BorderModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } 
واستخدم القطع من مكتبتنا في التطبيق
 import {Component, OnInit} from '@angular/core'; import {ListService} from 'test-lib'; @Component({ selector: 'app-root', template: ` <tl-list [list]="list"></tl-list> <div tlBorder>I am bordered now</div>`, styleUrls: ['./app.component.styl'] }) export class AppComponent implements OnInit { list: string[] = []; constructor(private svc$: ListService) { } ngOnInit() { this.svc$.list.subscribe((value => this.list = [...this.list, value])); } } 
تشغيل والتحقق من التطبيق ، كل شيء يعمل:

التجميع والنشر
يبقى لجمع ونشر الحزمة. للتجميع والنشر ، من المريح إضافة أوامر إلى البرامج النصية في تطبيق package.json
 { "name": "test-app", "version": "0.0.1", "scripts": { ... "lib:build": "ng build test-lib", "lib:watch": "ng build test-lib --watch", "lib:publish": "npm run lib:build && cd dist/test-lib && npm pack npm publish", ... } } 
يتم تجميع المكتبة ونشرها ، الآن بعد التثبيت في أي مشروع زاوي آخر
 npm install test-lib 
يمكنك استخدام المكونات والتوجيهات.
ملاحظة صغيرة
لدينا مجموعة كاملة من حزم npm في شركتنا ، لذلك في حالتنا يجب نشر الحزمة مع مساحة اسم كشركة / اختبار lib. للقيام بذلك ، سنقوم فقط بإجراء بعض التغييرات
إعادة تسمية الحزمة في مكتبة package.json
 /* projects/test-lib/package.json */ { "name": "@company/test-lib", "version": "0.0.1", "peerDependencies": { "@angular/common": "^7.2.0", "@angular/core": "^7.2.0" } } 
ومن ثم ، في تطبيق الاختبار ، يمكن الوصول إلى المكتبة بالاسم مع مساحة الاسم ، وسنصلح tsconfig قليلاً
 /* test-app/tsconfig.json */ *** "paths": { "@company/test-lib": [ "dist/test-lib" ], "@company/test-lib/*": [ "dist/test-lib/*" ] } *** 
وفي تطبيق الاختبار ، استبدل الواردات ، على سبيل المثال
 import {ListModule} from 'test-lib'; 
استبدال مع
 import {ListModule} from '@company/test-lib'; 
هذه هي النهاية.
ملاحظة: عندما درست هذا الموضوع ، قرأت المقالات التالية ذات مرة
سلسلة مكتبة الزاويكيفية بناء npm مكتبة مكون جاهزة مع الزاوي