Angular: criando e publicando uma biblioteca

Comece do começo


Se a memória me servir bem, a partir da versão 6 em ângulo, foi possível criar diferentes tipos de projetos em um espaço de trabalho: aplicativo e biblioteca.

Até o momento, as pessoas que desejavam criar uma biblioteca de componentes provavelmente usavam o excelente e útil pacote ng-packagr, que ajudou a criar o pacote no formato aceito para angular. Na verdade, eu criei a biblioteca anterior usando essa ferramenta. Agora, a equipe angular incluiu ng-packagr no angular-cli e adicionou esquemas para criar e construir bibliotecas, expandiu o formato angular.json e adicionou mais algumas comodidades. Agora vamos do ng new para o npm install - da criação de uma biblioteca vazia à publicação e importação no projeto de terceiros.

O espaço de trabalho é criado como de costume

ng new test-app 

O espaço de trabalho e o projeto do aplicativo serão criados, dê uma olhada no angular.json

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

Agora adicione o projeto da biblioteca

 ng generate library test-lib --prefix=tl 

adicionaremos a chave --prefix para indicar que os componentes e diretivas usarão o prefixo tl, ou seja, as tags do componente terão a aparência

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

Vamos ver agora em angular.json, adicionamos um novo projeto

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

A estrutura a seguir apareceu no diretório do projeto

 - 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 

Além disso, no tsconfig.json, há uma adição na seção caminhos

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

Agora, se você executar o aplicativo,
 ng serve 
então veremos um modelo de aplicativo angular de trabalho padrão

Criando funcionalidade da biblioteca


Vamos criar uma biblioteca com um serviço, diretiva e componente. Colocaremos o serviço e a diretiva em diferentes módulos. Vamos passar para o diretório projects / test-lib / src / lib e excluir test-lib. *. Ts, também excluir o conteúdo de projetos / test-lib / src / public-api.ts.

Vamos para projetos / test-lib / src / lib e criar módulos, diretiva, serviço e componente

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

Preencha o componente, serviço e diretiva com lógica. O componente exibirá uma lista de linhas enviadas para a entrada. A diretiva é adicionar um quadro vermelho, o serviço adicionará o carimbo de data / hora atual ao Observável a cada segundo.

Serviço

 /*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); } } 

Lista de componentes e módulo

 /*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() { } } 

Moldura

 /*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'; } } 

! É importante. Ao gerar componentes e bibliotecas, o cli não cria exportação, portanto, inclua os componentes e diretivas que devem estar disponíveis na seção de exportações nos módulos.

Além disso, para que, no futuro, as classes da biblioteca estejam disponíveis, adicionaremos algum código ao 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'; 

Conectando uma Biblioteca em um Aplicativo de Teste


Vamos montar o projeto da biblioteca

 ng build test-lib --watch 

Em seguida, no app.module, importaremos os módulos com o componente e a diretiva e adicionaremos a lógica

 /*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 { } 

E use as peças da nossa biblioteca no aplicativo

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

Execute e verifique o aplicativo, tudo funciona:



Montagem e publicação


Resta coletar e publicar o pacote. Para montagem e publicação, é conveniente adicionar comandos aos scripts no aplicativo 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", ... } } 

A biblioteca é compilada, publicada, agora após a instalação em qualquer outro projeto angular
 npm install test-lib 

Você pode usar componentes e diretivas.

Pequena nota


Temos uma família inteira de pacotes npm em nossa empresa, portanto, no nosso caso, o pacote deve ser publicado com o namespace como company / test-lib. Para fazer isso, faremos apenas algumas edições.

Renomeie o pacote na biblioteca 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" } } 

E para que no aplicativo de teste a biblioteca seja acessível por nome com espaço para nome, corrigiremos um pouco o tsconfig

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

E no aplicativo de teste, substitua as importações, por exemplo

 import {ListModule} from 'test-lib'; 

Substitua por

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

Esse é o fim

PS: Quando estudei esse tópico, li os seguintes artigos
A série de bibliotecas angulares

Como criar biblioteca de componentes prontos para npm com Angular

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


All Articles