Edición especial de Windows 10 de 2015

Volumen 30, número 11

Herramientas de Visual Studio: Las características de NuGet mejoran el desarrollo para Windows 10

Por Jeff Fitz | Windows 2015

Hay varias herramientas nuevas disponibles del equipo de NuGet. He trabajado con varios equipos en Microsoft para proporcionar una versión nueva del cliente NuGet que admita la Plataforma universal de Windows (UWP) y las nuevas bibliotecas de clases portátiles (PCL). Las nuevas herramientas de NuGet están disponibles en Visual Studio 2015, en Herramientas | Extensiones y actualizaciones | Actualización, así como en el sitio de distribución de NuGet: bit.ly/1MgNt2J. NuGet también ha lanzado una versión nueva de la herramienta de línea de comandos de NuGet que puede descargar desde la misma ubicación en dist.nuget.org. En este artículo se revisan las funcionalidades nuevas y el proceso que deben seguir los desarrolladores de Windows para que sus proyectos para Windows 10 sean compatibles con NuGet.

Project.Json

A partir de ASP.NET 5, NuGet es compatible con el archivo project.json para describir dependencias de proyecto con una definición más clara de los paquetes de los que dependería inmediatamente. En ASP.NET 5, este es el único archivo que define la configuración de proyectos. Sin embargo, con NuGet 3.1, puede usar este archivo en sus proyectos para la Plataforma universal de Windows y PCL modernas (orientadas a DNX, UWP y Microsoft .NET Framework 4.6) para definir referencias de paquetes. La buena noticia es que el cuadro de diálogo “Administrar paquetes” de Visual Studio mantendrá correctamente el archivo packages.config o project.json en función del tipo de proyecto que desarrolle.

Este cambio respecto al modelo packages.config también permite “reiniciar” las referencias de sus proyectos y usar las nuevas funcionalidades de dependencias transitivas de NuGet. Los desarrolladores y creadores de paquetes notificaron al equipo de NuGet que, cuando agregaban paquetes a proyectos, su archivo packages.config se contaminaba con dependencias de sus paquetes dependientes.

Por ejemplo, NHibernate es un paquete que depende del paquete lesi.Collections. En packages.config, hay dos referencias: NHibernate y Iesi.Collections. Cuando llega el momento de actualizar NHibernate, surge la pregunta: “¿Debo actualizar también Iesi.Collections?” También existe el problema contrario. Si hay una actualización para lesi.Collections, ¿también debo actualizar NHibernate para admitir las características nuevas de lesi.Collections? Para acabar con este incómodo círculo de administración de dependencias de paquetes de proyecto, los desarrolladores pueden usar referencias de paquetes.

La característica de dependencias transitivas de NuGet sintetiza esta decisión de actualizar referencias de paquetes con una mayor compatibilidad con las versiones de semántica mejorada en los archivos de definición de paquetes (documentos nuspecs). Los desarrolladores han especificado una amplia gama de versiones de dependencias que admiten sus paquetes. Cuando NuGet instala clientes, dichas dependencias agregan una referencia fuerte a una versión específica en el archivo packages.config y los paquetes referenciados tienen el mismo aspecto que cualquier otra referencia de paquete agregada al proyecto. Puede ver un buen ejemplo de este problema en la Ilustración 1.

Ilustración 1 Contenido de un archivo packages.config de ASP.NET MVC

<?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>

Al agregar estas cosas a mi proyecto, en realidad, solo necesito Microsoft.AspNet.Mvc, Microsoft.AspNet.Identity.EntityFramework, Newtonsoft.Json y Microsoft.Owin.Security.MicrosoftAccount. Los otros elementos a los que hacen referencia estos cuatro paquetes son solo ruido, y ahora tengo referencias fuertes a versiones específicas. Con la característica de dependencias transitivas, las versiones de estos otros paquetes desaparecen. Me queda administrar solo las cuatro bibliotecas que usaré en el proyecto.

El cliente NuGet resolverá y administrará estos otros paquetes en segundo plano por usted y mantendrá las referencias dentro de los límites de las versiones dependientes que declaren los paquetes que use en su proyecto. Esto debería simplificar drásticamente la experiencia con las referencias del proyecto.

Caché de paquete local común

A menudo, los desarrolladores tienen un conjunto de herramientas y paquetes preferidos. ¿Por qué descargarlos e instalarlos varias veces en la misma estación de trabajo cuando, claramente, ya los tiene en un proyecto y quiere usarlos en otro? Con los proyectos que administra project.json, NuGet descarga y almacena una copia de los paquetes en una carpeta de paquetes global ubicada en la carpeta %perfildeusuario%\.nuget\packages. Esto debería reducir el espacio en disco usado en la estación de trabajo. También evita las llamadas adicionales para obtener paquetes de NuGet.org para obtener elementos que ya tiene.

Project.json y la memoria caché de paquetes locales comunes están disponibles para ASP.NET 5 con NuGet 3.0 y, para otros tipos de proyecto, a partir de NuGet 3.1.

Características en desuso

A partir de NuGet 3.1, al usar project.json, no se admite la ejecución de los scripts install.ps1/­uninstall.ps1 y la entrega de elementos en la carpeta de paquetes /content. Al instalar paquetes con estos elementos, no se ejecutará el archivo install.ps1 ni se copiará contenido en el proyecto. Sin embargo, en los proyectos que aún usen los archivos packages.config, todavía se admitirá el comportamiento actual. Hay varios motivos:

  • Con la restauración de paquetes transitiva, es imposible elegir qué se instala y desinstala de forma fiable.
  • Al copiar contenido en el proyecto del usuario y actualizar los paquetes, hay un proceso de desinstalación implícito que no se puede ejecutar con confianza.
  • NuGet debe ser completamente compatible con el desarrollo fuera de Visual Studio. Con el movimiento para admitir completamente una experiencia de desarrollo .NET multiplataforma, Windows Powershell no está disponible en otros entornos. Cada vez más desarrolladores trabajan fuera de Visual Studio en código .NET y necesitan compatibilidad.
  • Otros administradores de paquetes ofrecen una gran experiencia para administrar y proporcionar contenido. NuGet funciona bien como administrador de paquetes para .NET Framework, por lo que se recomienda seguir usándolo.
  • Ya no se admite “cualquier” marco de trabajo. Ya no se pueden colocar archivos directamente en la raíz de la compilación y carpetas de bibliotecas para que se entreguen a un proyecto. Es importante declarar qué marcos de trabajo admiten los archivos para que NuGet tenga el orden de prioridad que debe seguir para resolver las referencias.
  • Los paquetes de soluciones ya no se admiten. Estos paquetes no modifican ninguna funcionalidad de proyecto específica y se solían usar para entregar recursos compartidos que se reutilizaban entre proyectos. Con la nueva carpeta de paquetes compartidos, puede que estos recursos ya estén en el disco de otro proyecto.

Nuevos marcos de trabajo de destino

Otro aspecto de esta versión nueva de NuGet es la compatibilidad con nuevos marcos de trabajo de desarrollo y una compatibilidad con paquetes nativos mejorada entre SO y arquitecturas. NuGet llega más allá del modelo administrado de .NET Framework para admitir más ecosistemas y permitirle usar bibliotecas en entornos a los que antes no se podía acceder.

Los monikers de la versión de .NET Framework de destino (TFM) se usan para acelerar la creación de un paquete que declare qué marcos de trabajo admiten los archivos binarios y qué dependencias necesita cada marco de trabajo. Encontrará nombres de carpeta en las carpetas de referencia y librerías de paquete que usan esta notación. También hay elementos en el elemento de dependencias nuspec del paquete que declaran un atributo del marco de trabajo de destino con uno de los valores de TFM para dirigir al cliente NuGet a que proporcione una biblioteca adecuada para un proyecto de consumo.

Los siguientes TFM aún están disponibles y los TFM nuevos que se presentan se enumeran en la Ilustración 2.

Ilustración 2 Marcos de trabajo de destino compatibles con NuGet 3.x

Descripción Código base Versiones disponibles
Aplicaciones de marco de trabajo administradas (Windows Forms, aplicaciones de consola, 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
Tienda Windows 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

Los elementos que se muestran con un símbolo igual (=) son sinónimos que admite NuGet. Es mucha compatibilidad para muchos marcos de trabajo distintos, pero puede confundir. ¿Necesita ofrecer compatibilidad para micro-marcos de trabajo en su paquete de marco de trabajo administrado? ¿Necesita mucha compatibilidad con Silverlight? Para satisfacer las necesidades de sus consumidores, debe responder a estas preguntas.

Observará que no hay ninguna llamada explícita para admitir PCL en la tabla. Aunque NuGet admite estas combinaciones de marcos de trabajo, quiere que tenga un moniker compatible con versiones posteriores para las PCL modernas. Esto le dará mayor flexibilidad a la hora de construir sus paquetes y definir los marcos de trabajo que admite. NuGet 3.1 incorpora el moniker de destino de dotnet para PCL modernas.

Moniker de destino de dotnet

En versiones anteriores de NuGet, se podían especificar los marcos de trabajo con una PLC que funcionaba como colección de abreviaturas de TFM unidas con símbolos más. Podía acabar con nombres de carpeta como “portable-net45+win8+wpa81+wp8”. Esto podía confundir y generar problemas de incompatibilidad para los consumidores. Para facilitar la experiencia de desarrollo multiplataforma y PCL, NuGet incorporó el moniker dotnet.

Este moniker no está directamente vinculado a las funcionalidades de ninguna versión ni marco de trabajo específicos. Es una referencia indirecta que indica a NuGet: “Esta es la referencia que debe usar si admite las funcionalidades de marco de trabajo y runtime que tiene”. A continuación, el cliente NuGet investiga dicha referencia para determinar las características y marcos que admite. Este proceso continúa hasta que el cliente NuGet resuelve las características exactas que admite la referencia de dotnet. A continuación, la aplicará si y solo si coincide con las características y requisitos del proyecto. Puede hacer referencia al moniker de dotnet con .NET Framework 4.5 y versiones de marco de trabajo derivadas posteriores, como Xamarin Android y Xamarin iOS.

Eso no significa que pueda limitarse a crear una PCL y empaquetarla con dependencias de dotnet declaradas sin más. Si quiere poder admitir proyectos con versiones anteriores Visual Studio y clientes NuGet a partir de bibliotecas de clases portátiles tradicionales, debe crear y hacer referencia al moniker de marco de trabajo de destino de PCL completo.

Al instalar un paquete en un tipo de proyecto totalmente compatible con el moniker dotnet (.NET Framework 4.6, UWP o ASP.NET 5), el moniker dotnet se buscará en último lugar. Esto pasará después de intentar buscar una referencia que coincida con el marco de trabajo o un marco de trabajo menos específico del proyecto. En la Ilustración 3 se muestra el aspecto de esta jerarquía.

Jerarquía de marcos de trabajo inspeccionados para referencias para un proyecto de Plataforma universal de Windows
Ilustración 3 Jerarquía de marcos de trabajo inspeccionados para referencias para un proyecto de Plataforma universal de Windows

Si el proyecto es una PCL moderna que usa project.json orientada a alguno de estos marcos de trabajo y a ningún otro, el moniker de dotnet se analizará en primer lugar. Esto irá seguido de la estrategia de resolución de PCL estándar, como se muestra en la Ilustración 4.

Jerarquía de marcos de trabajo inspeccionados para referencias para un proyecto de bibliotecas de clases portátiles modernas
Ilustración 4 Jerarquía de marcos de trabajo inspeccionados para referencias para un proyecto de bibliotecas de clases portátiles modernas

Línea de comandos de NuGet

Ahora, el ejecutable de tipo comando para NuGet, nuget.exe, permite instalar, actualizar y restaurar paquetes en un proyecto con un archivo packages.config o project.json. El comando de paquete sigue funcionando con archivos de nuspec del disco y archivos packages.config. No se ha actualizado para generar un archivo nuspec basado en un archivo project.json. Para solucionarlo, deberá crear su propio archivo de nuspec para cualquier paquete nuevo de contenido que cree con una referencia de paquetes de project.json. Una versión futura incluirá una actualización para solucionarlo.

Esta versión del ejecutable de línea de comandos también admite extremos de NuGet.org v3. Esta nueva versión de la fuente de nuget.org permite interacciones más rápidas y es un servicio más confiable. Cuenta con redundancia integrada y una red de entrega de contenido habilitada para ayudar a entregar paquetes rápidamente. Descargue una copia del ejecutable NuGet.exe actualizado desde bit.ly/1UV0kcU.

Si ha instalado el SDK de Windows 10/Herramientas de Windows 10 después de actualizar la extensión NuGet, el instalador instalará la versión 3.1 anterior de la extensión. Tendrá que volver a actualizarla a, al menos, la versión 3.1.1. La versión que se muestra en el cuadro de diálogo Extensiones y actualizaciones es 3.1.60724.766. La versión de la consola de Windows PowerShell es 3.1.1.0

Resumen

Ya están disponibles estas características que admiten el desarrollo de aplicaciones UWP de Windows 10 y los proyectos de PCL. Estos cambios son el primer paso para un uso más generalizado del administrador de paquetes y .NET Framework. Microsoft sigue mejorando la experiencia de desarrollo de .NET y se centrará en proporcionar un administrador de paquetes que puedan usar todos los desarrolladores de .NET en cualquier plataforma para crear cualquier tipo de proyecto.


Jeffrey T. Fritzes un administrador de programas sénior de Microsoft que trabaja en el equipo de NuGet. Le gustan los largos paseos por la playa y las aplicaciones web rompedoras que se escalan en la nube. Puede ponerse en contacto con él a través de la dirección jefritz@microsoft.com.

Gracias a los siguientes expertos técnicos por revisar este artículo: Miembros del equipo de NuGet de Microsoft