Uma introdução ao NuGet

Uma ferramenta essencial para qualquer plataforma de desenvolvimento moderna é um mecanismo por meio do qual os desenvolvedores podem criar, compartilhar e consumir código útil. Geralmente, esse código é fornecido em "pacotes" que contêm código compilado (como DLLs) juntamente com outro conteúdo necessário nos projetos que consomem esses pacotes.

Para o .NET (incluindo o .NET Core), o mecanismo com suporte da Microsoft para compartilhamento de código é o NuGet, que define como os pacotes do .NET são criados, hospedados e consumidos e fornece as ferramentas para cada uma dessas funções.

Em suma, um pacote do NuGet é um arquivo ZIP com a extensão .nupkg que contém o código compilado (DLLs), outros arquivos relacionados a esse código e um manifesto descritivo que inclui informações como o número de versão do pacote. Os desenvolvedores com código para compartilhar criam pacotes e os publicam em um host público ou privado. Os consumidores de pacote obtêm esses pacotes de hosts adequados, os adicionam aos seus projetos e chamam a funcionalidade de um pacote no código do projeto. Em seguida, o próprio NuGet manipula todos os detalhes de intermediários.

Como o NuGet oferece suporte a hosts privados junto com o host público nuget.org, é possível usar pacotes NuGet para compartilhar código exclusivo a uma organização ou a um grupo de trabalho. Você também pode usar os pacotes NuGet como uma forma conveniente de levar em consideração seu próprio código para uso em nada além de seus próprios projetos. Em resumo, um pacote NuGet é uma unidade compartilhável de código, mas não exige nem implica qualquer meio específico de compartilhamento.

O fluxo de pacotes entre criadores, hosts e clientes

Em sua função como um hospedeiro público, o NuGet mantém o repositório central de mais de 100 mil pacotes únicos em nuget.org. Esses pacotes são utilizados por milhões de desenvolvedores .NET/.NET Core todos os dias. O NuGet também permite hospedar pacotes em particular na nuvem (tais como o Azure DevOps), em uma rede privada ou até mesmo apenas nos seu sistema de arquivos local. Ao fazer isso, esses pacotes ficam disponíveis apenas aos desenvolvedores que têm acesso ao host, fornecendo a capacidade de tornar os pacotes disponíveis a um grupo específico de consumidores. As opções são explicadas em Hospedando seus próprios feeds do NuGet. Por meio de opções de configuração, você também pode controlar exatamente quais hosts podem ser acessados por um determinado computador, garantindo assim que os pacotes sejam obtidos de origens específicas, em vez de um repositório público como nuget.org.

Qualquer seja sua natureza, um host que serve como o ponto de conexão entre os criadores e os consumidores do pacote. Os criadores compilam pacotes do NuGet úteis e os publicam em um host. Os consumidores pesquisam então por pacotes úteis e compatíveis em hosts acessíveis, baixando e incluindo esses pacotes em seus projetos. Depois de instalado em um projeto, as APIs dos pacotes estão disponíveis para o restante do código do projeto.

Relationship between package creators, package hosts, and package consumers

Compatibilidade de direcionamento do pacote

Um pacote “compatível” significa que ele contém os assemblies criados para pelo menos um .NET framework de destino que seja compatível com a estrutura de destino do projeto consumidor. Os desenvolvedores podem criar pacotes específicos a uma estrutura, assim como acontece com os controles UWP, ou podem dar suporte a uma grande variedade de destinos. Para maximizar a compatibilidade de um pacote, os desenvolvedores direcionam para .NET Standard, que todos os projetos do .NET e .NET Core podem consumir. Esse é o meio mais eficiente para criadores e consumidores, pois um único pacote (geralmente contendo um único assembly) funciona para todos os projetos de consumo.

Por outro lado, os desenvolvedores de pacote que precisam de APIs fora do .NET Standard, criam assemblies separados para as estruturas de destino diferentes para as quais desejam dar suporte e incluem todos os assemblies no mesmo pacote (que é chamado de "multidirecionamento"). Quando um consumidor instalado um pacote como esse, o NuGet extrai apenas os assemblies que são necessárias para o projeto. Isso minimiza a superfície do pacote no aplicativo final e/ou assemblies produzidos pelo projeto. Um pacote multidirecionamento é, obviamente, mais difícil para o criador manter.

Observação

Para obter diretrizes sobre os componentes de aplicativos versus bibliotecas reutilizáveis, consulte a documentação do .NET Standard sobre o assunto.

Ferramentas do NuGet

Além da compatibilidade com a hospedagem, o NuGet também fornece uma variedade de ferramentas usadas por criadores e por consumidores. Veja Instalar as ferramentas de cliente do NuGet para saber como obter ferramentas específicas.

Ferramenta Plataformas Cenários Aplicáveis Descrição
CLI do dotnet Tudo Criação, Consumo Ferramenta CLI para bibliotecas .NET Core e .NET Standard, em projetos no estilo SDK que se destinam ao .NET Framework (confira o atributo do SDK). Fornece certas funcionalidades da CLI do NuGet diretamente na cadeia de ferramentas do .NET Core. Assim como ocorre com a CLI nuget.exe, a CLI dotnet não interage com projetos do Visual Studio.
CLI do nuget.exe Tudo Criação, Consumo Ferramenta CLI para bibliotecas do .NET Framework e projetos no estilo não SDK que se destinam a bibliotecas do .NET Standard. Fornece todos os recursos do NuGet, com alguns comandos de que aplicam especificamente aos criadores de pacote, alguns somente aos consumidores e outros a ambos. Por exemplo, os criadores de pacote usam o comando nuget pack para criar um pacote de vários assemblies e arquivos relacionados, os consumidores de pacote usam nuget install para incluir pacotes em uma pasta do projeto e todos usam nuget config para definir as variáveis de configuração do NuGet. Como uma ferramenta independente de plataforma, a CLI do NuGet não interage com projetos do Visual Studio.
Console do Gerenciador de Pacotes Visual Studio no Windows Consumo Fornece comandos do PowerShell para instalar e gerenciar pacotes em projetos do Visual Studio.
Interface do usuário do gerenciador de pacotes Visual Studio no Windows Consumo Fornece uma IU fácil de usar para instalar e gerenciar pacotes em projetos do Visual Studio.
Gerenciar a interface do usuário do NuGet Visual Studio para Mac Consumo Fornece uma IU fácil de usar para instalar e gerenciar pacotes em projetos do Visual Studio para Mac.
MSBuild Windows Criação, Consumo Fornece a capacidade de criar e restaurar os pacotes usados em um projeto diretamente por meio da cadeia de ferramentas do MSBuild.

Como você pode ver, as ferramentas do NuGet com as quais você trabalha dependem muito se você está criando ou consumindo pacotes, e a plataforma de trabalho na qual você está trabalhando. Os criadores de pacotes normalmente também são consumidores, pois eles aproveitam funcionalidades que existe em outros pacotes do NuGet. E, é claro, esses pacotes podem, por sua vez, depender de outros.

Para saber mais, comece com os artigos Fluxo de trabalho de criação de pacote e Fluxo de trabalho de consumo de pacote.

Gerenciamento de dependências

A capacidade de aproveitar facilmente o trabalho de outras pessoas é um dos recursos mais poderosos de um sistema de gerenciamento de pacotes. Da mesma forma, grande parte do que o NuGet faz é gerenciar essa árvore de dependência ou “grafo” em nome de um projeto. Em poucas palavras, você precisa apenas se preocupar com os pacotes que você está usando diretamente em um projeto. Se algum desses pacotes consumir outros pacotes (o que pode, por sua vez, consumir ainda mais), o NuGet cuidará de todas essas dependências de nível inferior.

A imagem a seguir mostra um projeto que depende de cinco pacotes, que por sua vez dependem de muitos outros.

An example NuGet dependency graph for a .NET project

Observe que alguns pacotes aparecem várias vezes no grafo de dependência. Por exemplo, há três consumidores diferentes do pacote B e cada consumidor também pode especificar uma versão diferente do pacote (não mostrado). Isso é uma ocorrência comum, especialmente para pacotes amplamente usados. Felizmente, o NuGet faz o trabalho duro para determinar exatamente qual versão do Pacote B atende a todos os consumidores. Em seguida, o NuGet faz o mesmo para todos os outros pacotes, independente da profundidade do grafo de dependência.

Para obter mais detalhes sobre como o NuGet executa esse serviço, consulte Resolução de dependência.

Rastreando referências e restaurando pacotes

Como projetos podem ser movidos facilmente entre os computadores de desenvolvedor, repositórios de controle do código-origem, servidores de build e assim por diante, é altamente impraticável manter assemblies binários dos pacotes do NuGet diretamente associados a um projeto. Isso tornaria cada cópia do projeto desnecessariamente sobrecarregada (e, assim, desperdiçaria espaço em repositórios de controle do código-origem). Também dificultaria muito a atualização de binários de pacote para versões mais recentes, pois as atualizações precisariam ser aplicadas em todas as cópias do projeto.

Em vez disso, o NuGet mantém uma lista de referências simples dos pacotes dos quais um projeto depende, incluindo dependências de nível superior e inferior. Ou seja, sempre que você instala um pacote de algum host em um projeto, o NuGet registra o identificador de pacote e o número de versão nesta lista de referência. (É claro que desinstalar um pacote o remove da lista.) o NuGet então fornece um meio de restaurar todos os pacotes referenciados mediante solicitação, conforme descrito em Restauração de Pacotes.

A NuGet reference list is created on package installation and can be used to restore packages elsewhere

Com apenas a lista de referências, o NuGet pode então reinstalar (ou seja, restaurar) todos esses pacotes de hospedeiros públicos e/ou privados posteriormente. Ao confirmar um projeto no controle do código-origem ou compartilhá-lo de alguma outra forma, você inclui apenas a lista de referências e exclui os binários do pacote (veja Pacotes e controle do código-origem.)

O computador que recebe um projeto, como um servidor de build obtendo uma cópia do projeto como parte de um sistema de implantação automatizada, simplesmente pede ao NuGet para restaurar as dependências sempre que necessário. Sistemas de build como o Azure DevOps fornecem etapas de “restauração do NuGet” para essa finalidade exata. Da mesma forma, quando os desenvolvedores obtêm uma cópia de um projeto (por exemplo, ao clonar um repositório), eles podem invocar um comando como nuget restore (CLI do NuGet), dotnet restore (CLI do dotnet) ou Install-Package (Console do Gerenciador de Pacotes) para obter todos os pacotes necessários. O Visual Studio, por sua vez, restaura automaticamente os pacotes ao compilar um projeto (contanto que a restauração automática esteja ativada, conforme descrito em Restauração de pacote).

Claramente, a função primária do NuGet, no que diz respeito aos desenvolvedores, é manter essa lista de referência em nome do seu projeto e fornecer os meios para restaurar (e atualizar) com eficiência os pacotes referenciados. Essa lista é mantida em um dos dois formatos de gerenciamento de pacote, como são chamados:

  • PackageReference (ou "referências de pacote em arquivos de projeto") |(NuGet 4.0 ou superior) Mantém uma lista de dependências de nível superior do projeto diretamente no arquivo de projeto, portanto, nenhum arquivo separado é necessário. Um arquivo associado, obj/project.assets.json, é gerado dinamicamente para gerenciar o grafo de dependência geral dos pacotes que um projeto usa juntamente com todas as dependências de nível inferior. PackageReference é sempre usado por projetos do .NET Core.

  • packages.config: (NuGet 1.0 ou superior) Como um arquivo XML que mantém uma lista simples de todas as dependências do projeto, incluindo as dependências de outros pacotes instalados. Os pacotes instalados ou restaurados são armazenados em uma pasta packages.

Qual formato de gerenciamento de pacotes é aplicado a um projeto depende do tipo de projeto e a versão disponível do NuGet (e/ou Visual Studio). Para verificar qual formato está sendo usado, simplesmente procure por packages.config na raiz do projeto depois de instalar o primeiro pacote. Se você não tiver esse arquivo, procure no arquivo de projeto diretamente por um elemento <PackageReference>.

Quando você tiver escolha, será recomendável usar PackageReference. packages.config é mantido para fins de legado e não está mais em desenvolvimento ativo.

Dica

Vários comandos da CLI do nuget.exe, como nuget install, não adicionam o pacote automaticamente à lista de referências. A lista é atualizada durante a instalação de um pacote com o Gerenciador de Pacotes do Visual Studio (interface do usuário ou Console) e com a CLI dotnet.exe.

O que mais o NuGet faz?

Até agora, você aprendeu as seguintes características do NuGet:

  • O NuGet fornece o repositório central nuget.org com suporte para a hospedagem privada.
  • O NuGet fornece as ferramentas que os desenvolvedores precisam para criar, publicar e consumir pacotes.
  • Mais importante, o NuGet mantém uma lista de referência de pacotes usados em um projeto e a capacidade de restaurar e atualizar esses pacotes da lista.

Para fazer com que esses processos funcionem com eficiência, o NuGet realiza algumas otimizações nos bastidores. Particularmente, o NuGet gerencia um cache de pacote e uma pasta de pacotes globais para abreviar a instalação e a reinstalação. O cache evita o download de um pacote já instalado no computador. A pasta de pacotes globais permite que vários projetos compartilhem o mesmo pacote instalado, reduzindo, assim, a superfície geral do NuGet no computador. As pastas de cache e de pacotes globais também são muito úteis quando você restaura com frequência um grande número de pacotes, como em um servidor de build. Para obter mais detalhes sobre esses mecanismos, confira Como gerenciar as pastas de pacotes globais e de cache.

Em um projeto individual, o NuGet gerencia o grafo de dependência geral, que inclui novamente a resolução de múltiplas referências para versões diferentes do mesmo pacote. É muito comum que um projeto adote uma dependência de um ou mais pacotes que tenham eles próprios as mesmas dependências. Alguns dos pacotes de utilitário mais úteis no nuget.org são utilizados por muitos outros pacotes. No grafo de dependência inteiro, dez, você poderia ter facilmente ter dez referências diferentes para diferentes versões do mesmo pacote. Para evitar trazer várias versões do pacote para o próprio aplicativo, o NuGet classifica qual versão única pode ser usada por qualquer consumidor. (Para saber mais, confira Resolução de dependência.)

Além disso, o NuGet mantém todas as especificações relacionadas a como os pacotes são estruturados (incluindo símbolos de localização e depuração) e como eles são referenciados (incluindo intervalos de versões e versões de pré-lançamento). O NuGet também fornece várias APIs para trabalhar com seus serviços programaticamente e fornece suporte para desenvolvedores que escrevem extensões do Visual Studio e modelos de projeto.

Reserve um tempo para navegar pelo sumário desta documentação e você verá todos esses recursos representados nele, junto com as notas de versão desde o início do NuGet.

Encontre mais vídeos sobre o NuGet no Channel 9 e no YouTube.

Comentários, contribuições e problemas

Por fim, apreciamos muito os comentários e contribuições para essa documentação. Basta selecionar os comandos Feedback e Editar no topo de qualquer página, ou visitar o repositório de documentos e a lista de problemas de documentos no GitHub.

Também aceitamos contribuições para o NuGet em si por meio de seus vários repositórios de GitHub; problemas do NuGet podem ser encontrados em https://github.com/NuGet/home/issues.

Aproveite sua experiência com o NuGet.