Edição especial do Windows 10 - 2015

Volume 30 - Número 11

Ferramentas do Visual Studio - Recursos do NuGet Aprimoram o Desenvolvimento do Windows 10

Por Jeff Fitz | Windows 2015

Várias novas ferramentas estão agora disponíveis por meio da equipe do NuGet. Ela trabalhou com várias equipes na Microsoft para fornecer uma nova versão do cliente do NuGet para dar suporte à UWP (Plataforma Universal do Windows) e às novas PCLs (Bibliotecas de Classes Portáteis). As novas ferramentas do NuGet estão disponíveis por meio de Ferramentas | Extensões e Atualizações | Atualização no Visual Studio 2015, bem como no site de distribuição do NuGet em bit.ly/1MgNt2J. O NuGet também lançou uma nova versão da ferramenta de linha de comando do NuGet que você pode baixar do mesmo local em dist.nuget.org. Este artigo examinará os novos recursos e o processo que os desenvolvedores do Windows precisam seguir para adicionar suporte do NuGet as seus projetos do Windows 10.

Project.Json

A partir do ASP.NET 5, o NuGet introduziu suporte para o arquivo project.json para descrever dependências de projeto com uma definição clara dos pacotes dos quais você dependeria imediatamente. No ASP.NET 5, esse é o único arquivo que define a configuração do projeto. Porém, com o NuGet 3.1, você usa esse arquivo em seus projetos Universais do Windows e PCLs modernas (que direcionam DNX, UWP e o Microsoft .NET Framework 4.6) para definir as referências de pacotes. A boa notícia é que a caixa de diálogo "Gerenciar Pacotes" no Visual Studio manterá adequadamente o arquivo packages.config ou project.json para você com base no tipo de projeto que você está desenvolvendo.

Essa mudança em relação ao modelo de packages.config também permite "reinicializar" referências em seus projetos e usar os novos recursos de dependência transitiva do NuGet. Os desenvolvedores e autores de pacotes relataram à equipe do NuGet que, quando adicionaram pacotes de projetos, o arquivo packages.config ficou poluído com dependências de seus pacotes dependentes.

Por exemplo, NHibernate é um pacote que depende do pacote Iesi.Collections. Em packages.config, há duas referências, NHibernate e Iesi.Collections. Quando é a hora de atualizar NHibernate, há a pergunta: "Também devo atualizar Iesi.Collections?" O problema oposto também existe. Se houver uma atualização para Iesi.Collections, precisarei atualizar NHibernate para dar suporte aos novos recursos de Iesi.Collections? Os desenvolvedores podem acabar nesse ciclo desagradável de gerenciar dependências de pacotes de seu projeto trazidas para eles por meio de referências de pacotes.

O recurso de dependências transitivas do NuGet abstrai essa decisão para atualizar referências a pacotes, com suporte melhorado para controle de versão semântico em arquivos de definição de pacote (documentos nuspec). Os desenvolvedores especificaram um intervalo de versões de dependências às quais seus pacotes dão suporte. Quando o NuGet instala clientes, essas dependências adicionam uma referência fixa a uma versão específica no arquivo packages.config, e os pacotes referenciados se parecem com qualquer outra referência de pacote que você tenha adicionado ao projeto. Você pode ver um ótimo exemplo desse problema na Figura 1.

Figura 1 - O conteúdo de um arquivo packages.config do MVC do ASP.NET

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Antlr" version="3.4.1.9004" targetFramework="net46" />
  <package id="bootstrap" version="3.0.0" targetFramework="net46" />
  <package id="EntityFramework" version="6.1.3" targetFramework="net46" />
  <package id="jQuery" version="1.10.2" targetFramework="net46" />
  <package id="jQuery.Validation" version="1.11.1" targetFramework="net46" />
  <package id="KendoUICore" version="2015.2.624" targetFramework="net46" />
  <package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net46" />
  <package id="Microsoft.AspNet.Identity.EntityFramework"
    version="2.2.1" targetFramework="net46" />
  <package id="Microsoft.AspNet.Identity.Owin" version="2.2.1" targetFramework="net46" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net46" />
  <package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net46" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net46" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net46" />
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform"
    version="1.0.0" targetFramework="net46" />
  <package id="Microsoft.jQuery.Unobtrusive.Validation"
    version="3.2.3" targetFramework="net46" />
  <package id="Microsoft.Net.Compilers"
    version="1.0.0" targetFramework="net46" developmentDependency="true" />
  <package id="Microsoft.Owin" version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Owin.Security.Cookies" version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Owin.Security.Facebook" version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Owin.Security.Google" version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Owin.Security.MicrosoftAccount"
    version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Owin.Security.OAuth" version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Owin.Security.Twitter" version="3.0.1" targetFramework="net46" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net46" />
  <package id="Modernizr" version="2.6.2" targetFramework="net46" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net46" />
  <package id="Owin" version="1.0" targetFramework="net46" />
  <package id="Respond" version="1.2.0" targetFramework="net46" />
  <package id="WebGrease" version="1.5.2" targetFramework="net46" />
</packages>

Quando adiciono esses itens a meu projeto, realmente só preciso de Microsoft.AspNet.Mvc, Microsoft.AspNet.Identity.EntityFramework, Newtonsoft.Json e Microsoft.Owin.Security.MicrosoftAccount. Os outros itens referenciados por esses quatro pacotes são irrelevantes, e agora tenho referências diretas a versões específicas. Com o recurso de dependências transitivas, as versões desses outros pacotes são eliminadas. Só preciso gerenciar as quatro bibliotecas que realmente usarei em meu projeto.

O cliente do NuGet resolverá e gerenciará esses outros pacotes nos bastidores para você e manterá as referências dentro das restrições das versões dependentes declaradas pelos pacotes que você está usando no projeto. Isso deve simplificar muito a experiência de referências do projeto.

Cache de pacote local comum

Frequentemente, os desenvolvedores têm uma "tribo" de pacotes e ferramentas que eles preferem. Por que baixá-los e instalá-los várias vezes em uma única estação de trabalho quando você claramente já os tem em um projeto e quer usá-los em outro? Com projetos gerenciados por project.json, o NuGet baixa e armazena uma cópia dos pacotes em uma pasta de pacotes globais localizada na pasta %userprofile%\.nuget\packages. Isso deve reduzir o espaço em disco usado na estação de trabalho. Também impede chamadas adicionais para buscar pacotes de NuGet.org para obter itens que você já tem.

Project.json e o suporte ao cache de pacote local comum estão disponíveis para ASP.NET 5 com NuGet 3.0 e para outros tipos de projeto a partir do NuGet 3.1.

Recursos preteridos

A partir do NuGet 3.1, ao usar project.json, você pretere o suporte para a execução dos scripts install.ps1/­uninstall.ps1 e o fornecimento de elementos na pasta de /content package. A instalação de pacotes com esses elementos não executará o arquivo install.ps1 nem copiará o conteúdo para o projeto. No entanto, em projetos que ainda usam arquivos packages.config, o comportamento atual ainda tem suporte. Há vários motivos para isso:

  • Com a restauração de pacotes transitiva, é impossível escolher de forma confiável o que desinstalar e instalar.
  • Quando você copia o conteúdo para o projeto do usuário e os pacotes são atualizados, há um processo de desinstalação implícita que você não pode executar de forma confiável.
  • O NuGet precisa dar suporte total ao desenvolvimento fora do Visual Studio. Com a transição para dar suporte a uma experiência completa de desenvolvimento do .NET de plataforma cruzada, o Windows PowerShell não está disponível em outros ambientes. Mais desenvolvedores também estão trabalhando fora do Visual Studio em código do .NET e precisam de suporte.
  • Outros gerenciadores de pacotes proporcionam uma ótima experiência para gerenciamento e fornecimento de conteúdo. O NuGet funciona bem como um gerenciador de pacotes para o .NET Framework, por isso, recomenda-se continuar a usá-lo.
  • Não há mais suporte para a estrutura "any". Você não pode mais colocar os arquivos diretamente na raiz das pastas de compilação e liberação para que eles sejam entregues a um projeto. É importante que você declare a quais estruturas seus arquivos dão suporte para que o NuGet saiba a ordem de prioridade para resolver essas referências.
  • Não há mais suporte para os pacotes de soluções. Esses pacotes não modificam recursos de nenhum projeto específico e, normalmente, eram usados para fornecer recursos compartilhados que eram reutilizados entre projetos. Com a nova pasta de pacotes compartilhados, esses recursos podem já estar no disco de outro projeto.

Novas estruturas de destino

Outro aspecto dessa nova versão do NuGet é o suporte a novas estruturas de desenvolvimento e o suporte melhorado a pacotes nativos entre sistemas operacionais e arquiteturas. O NuGet está se expandindo para além do modelo do .NET Framework para dar suporte a mais ecossistemas e capacitá-lo a usar bibliotecas em ambientes anteriormente inacessíveis.

TFM (monikers da estrutura de destino) é uma abreviação usada para criar um pacote para declarar a quais estruturas os binários dão suporte e de quais dependências cada estrutura necessita. Você encontrará nomes de pastas nas pastas lib e ref do pacote que usam essa notação. Também há elementos no elemento de dependências de nuspec do pacote que declaram um atributo de destino Framework com um dos valores de TFM para direcionar o cliente do NuGet a fornecer uma biblioteca apropriada a um projeto que vai consumi-la.

Os TFMs a seguir ainda estão disponíveis, e os novos TFMs que estão sendo introduzidos são listados na Figura 2.

Figura 2 - Estruturas de destino com suporte com o NuGet 3.x

Descrição Código base Versões disponíveis
Aplicativos de Estrutura Gerenciada (Windows Forms, Aplicativos de Console, Windows Presentation Foundation, ASP.NET) net net11, net20, net35, net35-client, net35-full, net4, net40, net40-client, net40-full, net403, net45, net451, net452, net46
ASP.NET 5 dnxcore dnxcore50
Windows Store netcore win8 = netcore45, win81 = netcore451, uap10.0
Windows Phone (modelo appx) wpa wpa81
Windows Phone (Silverlight) wp wp7 = sl3-wp, wp71 = sl4-wp71, sl4-wp, wp8 = wp8-, wp81
Silverlight sl sl2, sl3 = sl30, sl4 = sl40, sl5 = sl50
Xamarin   mono, MonoMac, Xamarin.Mac, MonoAndroid10, MonoTouch10, Xamarin.iOS10
Compact Framework net-cf net20-cf, net35-cf = cf35, net40-cf
Micro Framework netmf netmf41, netmf42, netmf43

Os itens listados com um sinal de igual (=) são sinônimos com suporte do NuGet. É muito suporte para muitas estruturas diferentes, mas isso pode ser confuso. Você precisa dar suporte a micro-framework em seu pacote de estrutura gerenciada? De quanto suporte ao Silverlight você precisa? Você precisa responder a essas perguntas para atender melhor às necessidades de seus consumidores.

Você notará que não há chamada explícita para dar suporte a PCLs na tabela. Embora o NuGet dê suporte a essas combinações de estruturas, ele quer que você tenha um moniker mais compatível com versões mais recentes para PCLs modernas. Isto lhe dará maior flexibilidade na criação de pacotes e na definição das estruturas às quais você dá suporte. O NuGet 3.1 introduz o moniker de destino dotnet para PCLs modernas.

Moniker de destino Dotnet

Em versões anteriores do NuGet, você podia especificar as estruturas com uma PCL que funcionavam como uma coleção de abreviações de TFM unidas com sinais de mais. Você podia acabar tendo nomes de pasta como "portable-net45+win8+wpa81+wp8". Isso podia ser confuso e levar a problemas de incompatibilidade para seus consumidores. Para facilitar a experiência de PCL e desenvolvimento de plataforma cruzada, o NuGet introduziu o moniker dotnet.

Esse moniker não está diretamente vinculado a recursos de nenhuma versão ou estrutura específica. É uma referência indireta que diz ao NuGet: "Esta é a referência que você deve usar se ela der suporte aos recursos de estrutura e de tempo de execução que você tem". Em seguida, o cliente do NuGet investiga a referência para determinar os recursos e estruturas aos quais ele dá suporte. Esse processo continua até que o cliente do NuGet determine as características exatas com suporte pela referência dotnet. Ele a aplicará então se e somente se ela corresponder aos recursos e requisitos de seu projeto. Você pode fazer referência ao moniker dotnet com o .NET Framework 4.5 e versões de estruturas derivadas posteriores, incluindo Xamarin Android e Xamarin iOS.

Isso não significa que você pode simplesmente criar uma PCL, empacotá-la com dependências dotnet declaradas e pronto. Se você quiser dar suporte a projetos usando versões mais antigas de clientes do Visual Studio e do NuGet compilando com bibliotecas de classes portáteis tradicionais, ainda deverá criar e colocar uma referência ao moniker de estrutura de destino de PCL completo.

Ao instalar um pacote em um tipo de projeto que é totalmente compatível com o moniker dotnet (.NET Framework 4.6, UWP ou ASP.NET 5), o moniker dotnet será procurado por último. Isso acontecerá após a tentativa de encontrar uma referência que corresponda à estrutura ou à estrutura menos específica de seu projeto. Essa hierarquia é semelhante à Figura 3.

Hierarquia de estruturas inspecionadas para referências a um projeto da Plataforma Universal do Windows
Figura 3 - Hierarquia de estruturas inspecionadas para referências a um projeto da Plataforma Universal do Windows

Se o seu projeto for uma PCL moderna usando project.json que direciona qualquer uma dessas estruturas e nenhuma outra, o moniker dotnet será analisado em primeiro lugar. Isso será seguido pela estratégia de resolução de PCL padrão, como mostrado na Figura 4.

Hierarquia de estruturas inspecionadas para referências em um projeto de biblioteca de classe portátil moderna
Figura 4 - Hierarquia de estruturas inspecionadas para referências em um projeto de biblioteca de classe portátil moderna

Linha de comando do NuGet

O executável semelhante a um comando para o NuGet, nuget.exe, agora está disponível com suporte para instalar, atualizar e restaurar pacotes para um projeto com um arquivo packages.config ou project.json. O comando pack continua a funcionar com arquivos nuspec em disco e arquivos packages.config. Ele não foi atualizado para gerar um arquivo nuspec com base em um arquivo project.json. Para contornar isso, você precisará criar seu próprio arquivo nuspec para qualquer novo conteúdo de pacote que criar com uma referência a pacotes project.json. Uma versão futura incluirá uma atualização para resolver isso.

Esta versão do executável da linha de comando também dá suporte a pontos de extremidade NuGet.org v3. Essa nova versão do feed de nuget.org fornece interações mais rápidas e é um serviço mais confiável. Há redundância interna e uma rede de entrega de conteúdo habilitada para auxiliar na entrega rápida de pacotes. Baixe uma cópia do NuGet.exe atualizado em bit.ly/1UV0kcU.

Se você instalou o SDK do Windows 10/ferramentas do Windows 10 depois de atualizar a extensão do NuGet, o instalador fará downgrade da extensão de volta para a Versão 3.1. Você precisará atualizá-lo novamente para pelo menos a versão 3.1.1. A versão que aparece na caixa de diálogo Extensões e Atualizações é 3.1.60724.766. O console do Windows PowerShell é 3.1.1.0.

Conclusão

Os recursos que dão suporte ao desenvolvimento de aplicativos de UWP do Windows 10 e projetos de PCL estão disponíveis agora. Essas alterações são a primeira etapa no uso mais amplo do gerenciador de pacotes e do .NET Framework. A Microsoft continua a melhorar a experiência de desenvolvimento do .NET e se concentrará em fornecer um gerenciador de pacotes para dar suporte a todos os desenvolvedores do .NET em qualquer plataforma, criando qualquer tipo de projeto.


Jeffrey T. Fritzé gerente de programa sênior na Microsoft, trabalhando na equipe do NuGet. Ele gosta de longas caminhadas na praia e de aplicativos Web incríveis que são dimensionados na nuvem. Entre em contato com ele pelo email jefritz@microsoft.com.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Membros da equipe do NuGet na Microsoft