Creare una libreria riutilizzabile con Angular - parte 2

di Morgan Pizzini, in HTML5, Angular,

Nello script #258 abbiamo introdotto le librerie mostrando le loro potenzialità per centralizzare il codice e ridurne al minimo la duplicazione. Ora andremo a ottimizzarne l'utilizzo rendendolo possibile anche all'esterno dell'applicazione.
Uno dei più grandi problemi quando si sviluppa è ricordarsi quale comando fa quella cosa. Fortunatamente, abbiamo a disposizione la sezione scripts del file package.json all'interno della quale possiamo inserire tutti gli script che ci consentono di gestire le funzionalità necessarie per lo sviluppo dell'applicazione. Nel prossimo esempio inseriamo i due script che consentono di eseguire la build della libreria.

"scripts": {
  ...
  "build_lib": "ng build my-app-lib",
  "build_lib:watch": "ng build my-app-lib --watch",
  ...
}

In ambiente Windows, all'esecuzione della build molto spesso ci si scontra con un errore simile a Error: EPERM: operation not permitted, unlink .... La causa è presto spiegata: la risorsa che si sta tentando di cancellare e ricreare con la build è utilizzata da un altro processo. Purtroppo questo è un problema noto le cui soluzioni sono molteplici e nessuna è definitiva. Cercando in rete ci si scontra facilmente con post in cui si da la colpa ad "Angular Language Service", a volte a VSCode a volte a Windows stesso. Per ridurre drasticamente questi errori la soluzione meno distruttiva e meno invadente, è l'inserimento all'interno del file tsconfig.json della seguente chiave.

"exclude": ["dist"]

In questo modo, il processo di TypeScript ignora la cartella dist evitando eventuali lock. Per ridurre ulteriormente la percentuale di errore, prima di ogni comando, possiamo richiedere la rimozione della cartella in cui è stata creata la libreria sempre utilizzando la sezione scripts del file packages.config.

"build_lib": "rimraf dist/my-app-lib && ng build my-app-lib",
"build_lib:watch": "rimraf dist/my-app-lib ng build my-app-lib --watch"

Un'altra situazione logorante è la sovrapposizione dei processi di build. Come ben sappiamo per poter avere un'anteprima web della nostra applicazione abbiamo bisogno di lanciare il comando ng serve. Con l'utilizzo di una libreria andiamo a utilizzare un secondo npm run build_lib:watc. Nel caso in cui avessimo più di una libreria abbiamo la necessità di utilizzare un'ulteriore console. Queste operazioni, anche se piccole, sono gravose in termini di tempo, perchè alla modifica di una libreria dovremo aspettare il processo di build della libreria e successivamente il processo di build di Angular che andrà ad applicare l'aggiornamento del bundle. La domanda 'ma chi me lo ha fatto fare?' arriva appena dopo la prima fase di test in cui ci siamo convinti di voler suddividere il nostro codice in più librerie. Per salvaguardare i nostri livelli di stess possiamo applicare una semplice modifica al file tsconfig.json, fin tanto che le modifiche nella libreria sono frequenti.

"paths": {
  "my-app-lib": [
    "projects/my-app-lib/src"
  ],
  "legit-my-app-lib": [
    "dist/my-app-lib"
  ],
  "legit-my-app-lib/*": [
    "dist/my-app-lib/*"
  ]
}

Successivamente, all'interno della cartella src della libreria inseriamo il file index.ts che esporterà il file public_api.ts. Questo passaggio è utile per mantenere la configurazione pulita, senza cioè puntare il file public_api.ts all'interno di paths.

export * from './public_api';

Con questa configurazione sarà possibile, durante la fase di sviluppo, utilizzare solo il comando ng serve perchè i file verranno recuperati direttamente della libreria. Una volta completata la fase di sviluppo si potrà eseguire la build e testarne il funzionamento rimuovendo il prefisso legit-.

Un altro package.json

Navigando tra i file notiamo come all'interno della libreria sia presente un file package.json il quale contiene il nome e la versione della libreria stessa. Queste informazioni serviranno a ng-packagr per produrre il pacchetto finale. All'interno di questo file è superfluo inserire la sezione devDependencies dato che avremo a disposizione tutte quelle inserite nel file package.json primario.

Riguardo alla sezione dependecies, abbiamo una grossa distinzione: dependencies e peerDependencies. Le prime sono le classiche dipendenze che al momento della build verranno incluse nel pacchetto; con le peerDependencies ci riferiamo alle dipendenze che l'applicazione, in cui verrà inclusa la libreria, dovrà avere per poter usufruire appieno delle funzionalità contenute nella libreria. Se l'applicazione non avrà i pacchetti richiesti, al momento dell'installazione, verrà presentato un warning.

Creare il package

A questo punto, la libreria è pienamente funzionante per il progetto all'interno della quale è stata creata. Ma cosa succede se vogliamo usarla all'esterno? Magari all'interno di un'altro progetto? Abbiamo creato un componente che gestisce tutte le modalità di signup e login e vogliamo riutilizzarlo in un'altra applicazione. Per creare il pacchetto ci viene in aiuto la libreria ng-packagr. A noi non resta altro che creare uno script che lanci il comando per creare la libreria partendo dalla cartella dist/my-app-lib. Per essere sicuri che il pacchetto creato sia coincidente con l'ultima versione compilata, possiamo creare un ulteriore script che esegua la build e crei il pacchetto.

"scripts": {
  ...
  "npm_pack": "cd dist/my-app-lib && npm pack",
  "package": "npm run build_lib && npm run npm_pack",
  ...
}

Quando avremo la necessità di utilizzare il pacchetto all'esterno possiamo utilizzare npm run package per poter creare il file .tgz contenente la libreria.

Installare la libreria in un altro progetto

E' possibile installare la libreria dall'esterno utilizzando npm install puntando il package tramite il percorso relativo. Supponendo quindi che le due cartelle dei progetti si trovino allo stesso livello, dalla seconda cartella possiamo utilizzare il comando npm install ../my-app/dist/my-app-lib/my-app-lib-0.0.1.tgz avendo l'accortezza di indicare correttamente la versione del pacchetto.
Possiamo anche inserire questo comando nella sezione scripts del package.json della nostra seconda applicazione.

"scripts": {
  ...
  "install_lib_local": "npm install ../my-app/dist/my-app-lib/my-app-lib-0.0.1.tgz",
  ...
}

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi