Pourquoi créer une librairie Angular réutilisable ?
Le bénéfice général est d’avoir un socle de code centralisé et réutisable sur tous vos projets Angular, qui peut évoluer indépendamment du code des projets avec ses propres mise à jour, ses propres corrections de bug, etc.
Plus spécifiquement, une librairie Angular vous permettra :
- De réutiliser des composants, notamment les éléments d’interface génériques qu’on retrouve dans de nombreux projets. Exemples : navbar, modale, champ de formulaire…
- De réutiliser des services, notamment la logique métier qui revient tout le temps. Exemples : authentification, accès à la base de données…
- De distribuer votre code. Une librairie correctement codée peut être consommée par tous les modules loaders, publiée sur le registre npm.
Difficultés pour créer une librairie Angular
- Gestion des dépendances — Choisir entre :
peerDependencies
: L’utilisateur de la librairie doit installer lui-même les dépendances dans son projet.embedded
: La librairie embarque le code de ses dépendances, mais risque de duplication.
- Format du package — La librairie doit être buildée !
- Format du bundle : FESM2015, FESM5, UMD…
- Librairie consommée via Angular CLI, Webpack, SystemJS ?
- Et aussi : générer les définitions de type (.d.ts), embedder les template et les CSS (en gérant les préprocesseurs comme SCSS ou less), etc.
⚠️ Attention : Ne tentez pas de builder la librairie manuellement
Les tâches mentionnées ci-dessus sont compliquées et il est déconseillé d’essayer de tout gérer manuellement. Mieux vaut partir d’un “starter” préconfiguré pour la génération de librairies Angular (voir ci-dessous).
La solution : ng-packagr
Qu’est-ce que ng-packagr ?
- https://github.com/dherges/ng-packagr permet de convertir un simple NgModule en librairie Angular.
- Respecte la recommandation officielle Angular Package Format.
- Résout tous les problèmes cités précédemment.
Comment utiliser ng-packagr ?
Créer un nouveau projet Angular avec le CLI :
ng new PROJECT
Installer ng-packagr :
cd path/to/PROJECT
npm install ng-packagr --save-dev
Créer un répertoire dédié à la librairie à la racine du projet :
/src
/app # Appli Angular
/my-lib
/src # Code source de la librairie (@NgModules, @Components…)
ng-package.json # Configuration de ng-packagr
package.json # package.json de la librairie finale
public_api.ts # Exporte les symboles publics de la librairie
L’appli Angular dans /src
peut servir de démo ou documentation sur l’usage de la librairie (on peut aussi la supprimer).
Ensuite, ajoutez des fonctionnalités à votre librairie (composants, directives, pipes, providers) comme vous le feriez dans une application Angular classique. Toutes les classes publiques de la librairie, c’est-à-dire celles que vous souhaitez utiliser explicitement dans vos projets, doivent être exportées du fichier public_api.ts
.
Quand votre librairie est prête, buildez-la avec la commande :
ng-packagr -p my-lib/ng-package.json
Il est conseillé de créer un script pour cette commande dans package.json
:
{
"scripts": {
// ...
"build:mylib": "ng-packagr -p my-lib/ng-package.json"
// ...
}
}
Vous pouvez maintenant builder la librairie avec la commande :
npm run build:mylib
Pour terminer, il faut rendre la librairie accessible dans votre projet Angular. Le plus simple est d’utiliser la commande npm link
pour créer un raccourci dans le répertoire node_modules
du projet Angular qui pointera sur le code buildé de la librairie.
Rendez-vous dans le répertoire du code buildé de la librairie :
cd path/to/dist-mylib
Rendez-vous dans le répertoire du code buildé de la librairie et tapez la commande npm link
:
cd path/to/dist-mylib
npm link
Puis, dans le projet Angular, créez un raccourci qui pointe vers la librairie :
npm link my-lib
Dans le répertoire node_modules
du projet Angular, vous devez maintenant voir un raccourci qui pointe vers votre librairie, comme si elle avait été installée en local dans le projet.
Dernier point de vigilance, ajoutez le flag --preserve-symlinks
aux commandes Angular CLI pour qu’elles suivent les raccourcis (ils sont ignorés par défaut). Par exemple :
{
"scripts": {
// ...
"start": "ng serve --preserve-symlinks",
// ...
}
}
⚠️ Worlflow de développement : Rebuilder la librairie + Relancer ng serve
Si vous travaillez simultanément sur votre librairie et le projet Angular qui la consomme, pensez bien à faire les tâches suivantes à chaque fois que vous changez le code de la librairie :
- Rebuilder la librairie (
npm run build:mylib
). - Arrêter et redémarrer
ng serve
dans le projet Angular pour prendre en compte la nouvelle version de la librairie.
NgModule librairie : Conventions à respecter
Rappel : Une librairie Angular est un NgModule
Une librairie Angular est juste un NgModule respectant certaines conventions et buildé d’une certaine manière. Par exemple, le code d’Angular n’est pas embarqué dans le code de la librairie, puisqu’elle sera utilisée dans un projet où Angular sera déjà présent.
Conventions à respecter :
- Un NgModule librairie peut avoir des
declarations
(composants, directives, pipes), desproviders
(services), et desexports
(de NgModules ou déclarations). - Un NgModule librairie ne doit PAS avoir de propriété
bootstrap
. - Un NgModule librairie doit implémenter une méthode
forRoot()
s’il contient des providers, ou s’il nécessite des paramètres de configuration.
Erreurs fréquentes avec ng-packagr
- Ne pas utiliser la bonne syntaxe d’import dans le code de sa librairie.
- Oublier d’embedder une dépendance qui risque de ne pas être présente dans le projet client.