Il est essentiel pour toute plateforme de développement moderne de proposer un mécanisme permettant aux développeurs de créer, de partager et d’exploiter le code qui leur est utile. Souvent, ce code est groupé en « packages » contenant le code compilé (sous forme de DLL) ainsi que tout le contenu nécessaire aux projets qui les utilisent.
Dans le cas de .NET (y compris .NET Core), le mécanisme de partage de code pris en charge par Microsoft est NuGet. Il définit la façon dont les packages .NET sont créés, hébergés et utilisés, et fournit des outils pour chacun de ces rôles.
Pour faire simple, un package NuGet est un fichier ZIP avec l’extension .nupkg, qui contient du code compilé (des DLL), d’autres fichiers liés à ce code et un manifeste descriptif qui inclut des informations comme le numéro de version du package. Les développeurs qui ont du code à partager créent des packages et les publient sur un hôte public ou privé. Les consommateurs récupèrent ces packages auprès des hôtes correspondants, les ajoutent à leurs projets, puis appellent leurs fonctionnalités dans le code de leur projet. NuGet gère ensuite lui-même tous les détails intermédiaires.
NuGet prenant en charge à la fois les hôtes privés et l’hôte nuget.org public, il est possible d’utiliser des packages NuGet pour partager du code dont une organisation ou un groupe de travail a l’exclusivité. Ils représentent également un moyen pratique d’intégrer son propre code pour l’utiliser uniquement dans ses propres projets. En bref, un package NuGet est une unité de code partageable, qui ne nécessite ni n’implique aucun mode de partage en particulier.
Flux des packages entre les créateurs, les hôtes et les consommateurs
Dans son rôle d’hôte public, NuGet gère lui-même le référentiel central de plus de 100 000 packages uniques à nuget.org. Ces packages sont utilisés par des millions de développeurs .NET/.NET Core tous les jours. NuGet vous permet également d’héberger des packages à titre privé dans le cloud (par exemple sur Azure DevOps), sur un réseau privé ou même seulement sur votre système de fichiers local. Ces packages sont ainsi réservés aux développeurs qui ont accès à l’hôte, ce qui permet de les mettre à la disposition d’un groupe spécifique de consommateurs. Les options sont expliquées dans Hébergement de vos propres flux NuGet. Les options de configuration permettent également de choisir précisément quels hôtes seront accessibles à chaque ordinateur, ce qui garantit que les packages proviendront de sources spécifiques plutôt que d’un référentiel public comme nuget.org.
Quelle que soit sa nature, un hôte sert de point de connexion entre les créateurs et les consommateurs de packages. Les créateurs produisent des packages NuGet pratiques et les publient sur un hôte. Les consommateurs recherchent des packages pratiques et compatibles sur les hôtes accessibles, les téléchargent et incluent ces packages dans leurs projets. Une fois installés dans un projet, les API des packages sont disponibles pour le reste du code du projet.
Compatibilité du ciblage de packages
Un package « compatible » est un package qui contient des assemblies créés pour au moins une version cible de .NET Framework compatible avec celle du projet qui utilise le package. Les développeurs peuvent soit créer des packages propres à une version, comme avec les contrôles UWP, soit prendre en charge un éventail plus large de versions cibles. Pour optimiser la compatibilité d’un package, ils ciblent .NET Standard, que tous les projets .NET et .NET Core peuvent exploiter. C’est le moyen le plus efficace tant pour les créateurs que pour les consommateurs, car un package unique (qui contient généralement un seul assembly) fonctionne pour tous les projets.
Les développeurs de packages qui ont besoin d’API extérieures à .NET Standard, quant à eux, créent un assembly distinct pour chacune des versions cibles de .NET Framework qu’ils souhaitent prendre en charge, et les intègrent tous dans le même package (« ciblage multiple »). Lorsque un consommateur installe un package de ce type, NuGet extrait seulement les assemblies nécessaires au projet. Ceci réduit l’encombrement du package dans l’application finale et/ou dans les assemblys produits par ce projet. Un package à ciblage multiple est, bien sûr, plus difficile à gérer pour son créateur.
En plus de la prise en charge de l’hébergement, NuGet fournit également différents outils utilisés à la fois par les créateurs et par les consommateurs. Pour obtenir des outils spécifiques, consultez Installation des outils clients NuGet.
Outil CLI pour les bibliothèques .NET Core et .NET Standard et pour les projets de style SDK qui ciblent le .NET Framework (consultez Attribut SDK). Propose certaines des fonctionnalités de l’interface CLI NuGet directement dans la chaîne d’outils .NET Core. Tout comme l’interface CLI nuget.exe, l’interface CLI dotnet n’interagit pas avec les projets Visual Studio.
Outil CLI pour les bibliothèques .NET Framework et les projets qui ne sont pas de style SDK ciblant les bibliothèques .NET Standard. Fournit toutes les fonctionnalités de NuGet, avec certaines commandes s’appliquant spécifiquement aux créateurs de package, certaines seulement aux consommateurs et d’autres aux deux. Par exemple, les créateurs de packages utilisent la commande nuget pack pour créer un package à partir de différents assemblies et des fichiers associés, les consommateurs utilisent nuget install pour inclure des packages dans un dossier de projet, et tous utilisent nuget config pour définir les variables de configuration NuGet. L’interface CLI NuGet, indépendante de la plateforme, n’interagit pas avec les projets Visual Studio.
Offre la possibilité de créer et de restaurer directement des packages utilisés dans un projet avec la chaîne d’outils MSBuild.
Comme on peut le constater, les outils NuGet à utiliser dépendent fortement de l’activité (création, utilisation ou publication de packages), ainsi que de la plateforme utilisée. Les créateurs de packages en sont en général également des consommateurs, car ils s’appuient sur des fonctionnalités qui existent dans d’autres packages NuGet. Bien sûr, ces packages peuvent à leur tour dépendre d’autres packages.
La facilité à s’appuyer sur le travail des autres est l’un des aspects les plus puissants d’un système de gestion des packages. En conséquence, la plus grande partie du travail effectué par NuGet consiste à gérer cette arborescence ou ce « graphique » de dépendance pour chaque projet. Autrement dit, vous devez vous préoccuper seulement des packages que vous utilisez directement dans un projet. Si l’un d’entre eux utilise lui-même d’autres packages (et ainsi de suite), NuGet se charge de toutes ces dépendances des niveaux inférieurs.
L’illustration suivante montre un projet qui dépend de cinq packages, qui à leur tour dépendent de plusieurs autres.
Notez que certains packages apparaissent plusieurs fois dans le graphe des dépendances. Par exemple, il existe trois consommateurs différents du package B, et chaque consommateur peut également spécifier une version différente pour ce package (non représenté). C’est un cas courant, en particulier pour les packages les plus utilisés. Heureusement, NuGet se charge de tout le travail en identifiant exactement la version du package B qui convient à tous les consommateurs. NuGet fait ensuite de même pour tous les autres packages, quelle que soit la profondeur du graphique de dépendance.
Pour plus d’informations sur la façon dont NuGet réalise ce service, consultez Résolution des dépendances.
Suivi des références et restauration de packages
Compte tenu de la simplicité de déplacement de projets entre différents ordinateurs de développeurs, référentiels de contrôle de code source, serveurs de builds, etc., il est très peu pratique de conserver les assemblys binaires de packages NuGet directement liés à un projet. Cela aurait pour effet d’encombrer inutilement chacune des copies du projet (et ainsi de gaspiller de l’espace dans les référentiels de contrôle de code source). Il serait également très difficile de mettre à jour les fichiers binaires des packages, car la nouvelle version devrait s’appliquer à toutes les copies du projet.
NuGet gère plutôt une simple liste de références des packages dont dépend le projet, qui englobe les dépendances de niveau supérieur et de niveau inférieur. Autrement dit, lorsque un package est installé dans un projet à partir d’un hôte, NuGet enregistre l’identificateur et le numéro de version du package dans cette liste de références. (La désinstallation d'un package le supprime bien entendu de la liste) NuGet offre un moyen de restaurer tous les packages référencés à la demande, comme le décrit la section Restauration de packages.
Avec seulement la liste des références NuGet peut alors à tout moment réinstaller, autrement dit, restaurer, tous ces packages à partir d’hôtes publics et/ou privés. Pour valider un projet dans le contrôle de code source ou le partager par un autre moyen, il suffit d’inclure la liste des références et d’exclure les fichiers binaires des packages (consultez la section Packages et contrôle de code source.)
L’ordinateur qui reçoit un projet, par exemple un serveur de builds obtenant une copie du projet dans le cadre d’un système de déploiement automatisé, demande simplement à NuGet de restaurer les dépendances quand elles sont nécessaires. Les systèmes de build, comme Azure DevOps, fournissent des étapes de « restauration NuGet » à cette fin. De même, lorsque les développeurs récupèrent une copie d’un projet (par exemple, en clonant un référentiel), ils peuvent appeler une commande du type nuget restore (interface CLI NuGet), dotnet restore (interface CLI dotnet) ou Install-Package (console du Gestionnaire de package) pour avoir tous les packages nécessaires. Visual Studio, pour sa part, restaure automatiquement les packages lors de la création d’un projet (tant que la restauration automatique est activée, comme l’explique la page Restauration de package).
Le rôle principal de NuGet pour les développeurs est clairement de gérer cette liste de références pour le compte de votre projet, et de fournir les moyens de restaurer efficacement (et de mettre à jour) les packages référencés. Cette liste est gérée dans un des deux formats de gestion des packages, nommés :
PackageReference (ou « Références des packages dans les fichiers projet ») : (NuGet 4.0+) Gère la liste des dépendances de niveau supérieur d’un projet directement dans le fichier projet ; aucun fichier distinct n’est nécessaire. Un fichier associé, obj/project.assets.json, est généré dynamiquement pour gérer le graphique de dépendance global des packages utilisés par un projet, ainsi que toutes les dépendances de bas niveau. PackageReference est toujours utilisé par les projets .NET Core.
packages.config: (NuGet 1.0+) Un fichier XML qui gère une liste plate de toutes les dépendances du projet, y compris les dépendances des autres packages installés. Les packages installés ou restaurés sont stockés dans un dossier packages.
Le format de gestion des packages utilisé dépend du type de projet, ainsi que de la version disponible de NuGet (ou de Visual Studio). Pour savoir quel format est utilisé, recherchez packages.config dans la racine du projet après avoir installé votre premier package. Si vous ne possédez pas ce fichier, recherchez l’élément <PackageReference> directement dans le fichier projet.
Si vous avez le choix, nous vous recommandons d’utiliser PackageReference. packages.config est conservé pour des raisons d’héritage et ne fait plus l’objet d’un développement actif.
Conseil
Diverses commandes CLI nuget.exe, comme nuget install, n’ajoutent pas automatiquement le package à la liste de référence. La liste est mise à jour lors de l’installation d’un package avec le Gestionnaire de package de Visual Studio (interface utilisateur ou console) et l’interface CLI dotnet.exe.
Autres fonctionnalités de NuGet
Nous avons vu jusqu’ici les caractéristiques suivantes de NuGet :
NuGet propose le référentiel central nuget.org, qui prend en charge l’hébergement privé.
NuGet fournit les outils dont les développeurs ont besoin pour créer, publier et consommer des packages.
Plus important encore, NuGet gère la liste des références des packages utilisés dans le projet, et a la capacité de restaurer et de mettre à jour ces packages à partir de cette liste.
Pour que ces processus fonctionnent efficacement, NuGet effectue certaines optimisations en arrière-plan. En particulier, NuGet gère un cache de package et un dossier de packages globaux pour accélérer l’installation et la réinstallation. Le cache évite d’avoir à télécharger un package déjà installé sur l’ordinateur. Grâce au dossier de packages globaux, plusieurs projets peuvent partager le même package installé, ce qui réduit l’encombrement global de NuGet sur l’ordinateur. Le cache et le dossier de packages globaux sont également très pratiques pour restaurer fréquemment un grand nombre de packages, comme sur un serveur de builds. Pour plus d’informations sur ces mécanismes, consultez Gérer les dossiers de packages globaux et de cache.
Pour un projet donné, NuGet gère le graphique de dépendance global, ce qui implique de résoudre à nouveau des références multiples à différentes versions du même package. Il est fréquent qu’un projet ait une dépendance d’un ou plusieurs packages qui ont eux-mêmes les mêmes dépendances. Par exemple, certains des packages utilitaires les plus pratiques de nuget.org sont utilisés par beaucoup d’autres packages. Pris dans sa totalité, le graphique de dépendance peut facilement comporter dix références distinctes à des versions différentes du même package. Pour éviter d’importer plusieurs versions de ce package dans l’application elle-même, NuGet repère la version utilisable par tout le monde. (Pour plus d’informations, consultez la page Résolution des dépendances.)
Prenez le temps de parcourir la table des matières de cette documentation : toutes ces fonctionnalités y sont représentées, ainsi que des notes de publication remontant aux débuts de NuGet.
Enfin, les commentaires et les contributions à cette documentation sont les bienvenus sélectionnez simplement les commandes Commentaires et Modifier en haut d’une page, ou consultez le référentiel de documents et la liste des documents consacrés aux problèmes sur GitHub.
Créez un projet .NET et apprenez à ajouter des packages et à gérer les dépendances de package de votre projet. Utilisez CLI .NET Core et le registre NuGet pour ajouter des bibliothèques et des outils à vos applications C# par le biais de Visual Studio Code.