Angular: création et publication d'une bibliothèque

Partir du début


Si la mémoire me sert bien, alors à partir de la version 6 en angulaire, il est devenu possible de créer différents types de projets dans un seul espace de travail: application et bibliothèque.

Jusqu'à ce point, les gens qui voulaient créer une bibliothèque de composants utilisaient très probablement l'excellent et utile package ng-packagr, qui aidait à créer le package dans le format accepté pour angular. En fait, j'ai créé la bibliothèque précédente en utilisant cet outil. Maintenant, l'équipe angulaire a inclus ng-packagr dans angular-cli et a ajouté des schémas pour créer et construire des bibliothèques, a étendu le format angular.json et ajouté quelques autres commodités. Passons maintenant de ng new à npm install - de la création d'une bibliothèque vide à sa publication et son importation dans un projet tiers.

L'espace de travail est créé comme d'habitude

ng new test-app 

L'espace de travail et le projet d'application seront créés, jetez un œil à angular.json

 { ... "projects": { "test-app": { ... "sourceRoot": "src", "projectType": "application", "prefix": "app" ... } ... } ... } 

Maintenant, ajoutez le projet de bibliothèque

 ng generate library test-lib --prefix=tl 

nous ajouterons la clé --prefix pour indiquer que les composants et les directives utiliseront le préfixe tl, c'est-à-dire que les balises des composants ressembleront à

 <tl-component-name></tl-component-name> 

Voyons maintenant dans angular.json, nous avons ajouté un nouveau projet

 { ... "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" } ... } ... } 

La structure suivante est apparue dans le répertoire du projet

 - 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 

De plus, dans tsconfig.json, il y a un ajout dans la section des chemins

 "paths": { "test-lib": [ "dist/test-lib" ], "test-lib/*": [ "dist/test-lib/*" ] } 

Maintenant, si vous exécutez l'application,
 ng serve 
alors nous verrons un modèle d'application angulaire de travail standard

Création de fonctionnalités de bibliothèque


Créons une bibliothèque avec un service, une directive et un composant. Nous placerons le service et la directive dans différents modules. Passons au répertoire projects / test-lib / src / lib et supprimons test-lib. *. Ts, supprimons également le contenu de projects / test-lib / src / public-api.ts.

Passons à projets / test-lib / src / lib et créons des modules, directive, service et composant

 ng g module list ng g module border ng g service list /*  list*/ ng g component list /*  border*/ ng g directive border 

Remplissez le composant, le service et la directive de logique. Le composant affichera une liste des lignes soumises à l'entrée. La directive est d'ajouter un cadre rouge, le service ajoutera l'horodatage actuel à l'Observable chaque seconde.

Le service

 /*list.service.ts*/ 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); } } 

Liste des composants et module

 /*list.module.ts*/ 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 { } /*list.component.ts*/ @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() { } } 

Cadre

 /*border.module.ts*/ 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 { } /*border.directive.ts*/ 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'; } } 

! C'est important. Lors de la génération de composants et de bibliothèques, cli ne crée pas d'exportation, assurez-vous donc d'ajouter les composants et les directives qui devraient être disponibles dans la section d'exportation des modules.

De plus, afin que dans le futur des classes de la bibliothèque soient disponibles, nous ajouterons du code à public-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'; 

Connexion d'une bibliothèque dans une application de test


Assemblons le projet de bibliothèque

 ng build test-lib --watch 

Ensuite, dans app.module, nous importerons les modules avec le composant et la directive et ajouterons la logique

 /*app.module.ts*/ 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 { } 

Et utilisez les morceaux de notre bibliothèque dans l'application

 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])); } } 

Exécutez et vérifiez l'application, tout fonctionne:



Assemblage et publication


Reste à collecter et publier le package. Pour l'assemblage et la publication, il est pratique d'ajouter des commandes aux scripts dans l'application 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", ... } } 

La bibliothèque est compilée, publiée, maintenant après l'installation dans tout autre projet angulaire
 npm install test-lib 

Vous pouvez utiliser des composants et des directives.

Petite note


Nous avons toute une famille de packages npm dans notre entreprise, donc dans notre cas, le package doit être publié avec un espace de noms en tant que company / test-lib. Pour ce faire, nous allons simplement apporter quelques modifications

Renommez le package dans la bibliothèque 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" } } 

Et pour que dans l'application de test la bibliothèque soit accessible par son nom avec un espace de noms, nous allons corriger un peu tsconfig

 /* test-app/tsconfig.json */ *** "paths": { "@company/test-lib": [ "dist/test-lib" ], "@company/test-lib/*": [ "dist/test-lib/*" ] } *** 

Et dans l'application de test, remplacez les importations, par exemple

 import {ListModule} from 'test-lib'; 

Remplacez par

 import {ListModule} from '@company/test-lib'; 

C'est la fin.

PS: Quand j'ai étudié ce sujet, j'ai lu une fois les articles suivants
La série des bibliothèques angulaires

Comment créer une bibliothèque de composants prêts pour npm avec Angular

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


All Articles