Minimizando hojas de estilos y scripts con Visual Studio

Generalmente cuando queremos pasar nuestras aplicaciones web ASP.NET o MVC ASP.NET a producción lo hacemos a través de la opción Publicar de Visual Studio. Esto funciona bien en aplicaciones sencillas, pero no es siempre lo que necesitamos. Supongamos que necesitamos automatizar ciertos aspectos de la implementación, que en nuestro caso será minificar los archivos CSS y JS antes de crear la aplicación final. Para estos casos podemos usar los proyectos Web Deployment Project.

El primer paso para poder utilizar este tipo de proyectos (no vienen por default en Visual Studio) y poder minimizar los archivos será instalar lo siguiente:

En este caso vamos a crear una aplicación web ASP.NET MVC 2.0 que llamaremos MvcEjemplo y le vamos a agregar algunos archivos CSS y script JS, que luego vamos a minimizar. Además de la aplicación web vamos a agregar a la solución un proyecto del tipo Web Deployment Project donde vamos a realizar las configuraciones necesarias para poder minimizar nuestros archivos.

Para agregar este tipo de proyecto, primero seleccionamos la aplicación web, y luego vamos a la opción “Build > Add Web Deployment Project”. Seleecionada esta opción llamaremos a nuestro nuevo proyecto MvcEjemplo.Deploy.

Estructura de la solución

Estructura de la solución

Agregado el proyecto, vamos a realizar la primera configuración para que los cambios siempre se apliquen sobre nuestra aplicación en modo Release. Para ello hacemos click derecho sobre el proyecto y vamos a la opción “Properties Windows”, dentro de la misma lo configuramos de la siguiente forma:

Configurando el proyecto

Configurando el proyecto

Existen otras configuraciones que en el ejemplo no las vamos a ver, pero que pueden serles muy útiles.

Una vez terminados estos pasos, vamos a comenzar las modificaciones, para esto hacemos click derecho sobre el proyecto y vamos a la opción “Open Project File”, la cual nos va a desplegar el archivo de configuración (un documento XML) en donde vamos a trabajar:

Abriendo el archivo del proyecto

Abriendo el archivo del proyecto

En el archivo de configuración el primer paso será hacer referencia a la librería Ajax Minifier, que nos va a proporcionar los métodos necesarios para poder minimizar nuestros archivos:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />

La secciones dentro del XML de configuración que nos interesan en este caso son las encerradas dentro de los tags Target. El primero que vamos a modificar es el target “AfterMerge“. Dentro del mismo lo que vamos hacer es unificar todos los scripts JS del directorio “Script” (no tenemos en cuenta los que se encuentran en “Script\MyScripts” y nuestras hojas de estilos CSS en un único archivo para cada tipo (aclaro que unificamos dichos archivos en uno solo, ya que estos scripts y estilos suponemos se utilizan en todo el sitio y se referencian una única vez). Para esto agregamos lo siguiente:

<ItemGroup>
   <JsFiles Include="$(TempBuildDir)\Scripts\*.js;" Exclude="$(TempBuildDir)\Scripts\*.min.js;" />
   <CssFiles Include="$(TempBuildDir)\Content\*.css;" />
</ItemGroup>

Lo que hicimos fui incluir todos los archivos de script “JS” que se encuentran en el directorio “Scripts/” excepto los que terminen con la extensión “.min.js” (ya que los mismos ya se encuentran minimizados). Hacemos lo mismo con los archivos “CSS” que se encuentran en el directorio “Content” solo que en este caso no estamos excluyendo ninguno.

Hecho este paso, vamos a decir que todos los scripts que incluimos los escriba en un único archivo llamado AllJs.js:

<!-- Scripts Js -->
<ReadLinesFromFile File="%(JsFiles.Identity)">
   <Output TaskParameter="Lines" ItemName="jsLines" />
</ReadLinesFromFile>
<WriteLinesToFile File="$(TempBuildDir)\Scripts\AllJs.js" Lines="@(jsLines)" Overwrite="true" />

Para los archivos de estilos hacemos lo mismo pero en el archivo AllCss.css:

<!-- Css -->
<ReadLinesFromFile File="%(CssFiles.Identity)">
   <Output TaskParameter="Lines" ItemName="cssLines" />
</ReadLinesFromFile>
<WriteLinesToFile File="$(TempBuildDir)\Content\AllCss.css" Lines="@(cssLines)" Overwrite="true" />

Ahora vamos a trabajar en el Target “AfterBuild“. Lo que vamos a hacer es definir que archivos queremos minimizar, en nuestro caso los dos archivos que acabamos de “crear” y los script del directorio “MyScripts” por separados:

<ItemGroup>
   <JS Include="**\Scripts\AllJs.js;" />
   <JSMyScripts Include="**\Scripts\MyScripts\*.js;" />
</ItemGroup>
<ItemGroup>
   <CSS Include="**\Content\AllCss.css;" />
</ItemGroup>

Lo siguiente es “minimizar” dichos archivos:

<AjaxMin JsSourceFiles="@(JS)"
          JsSourceExtensionPattern="\.js$"
          JsTargetExtension=".min.js"
          CssSourceFiles="@(CSS)"
          CssSourceExtensionPattern="\.css$"
          CssTargetExtension=".min.css" />
<AjaxMin JsSourceFiles="@(JSMyScripts)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" />

Finalmente podemos “eliminar” aquellos archivos que fueron minimizados y que no van a ser utilizados por tal motivo, por ejemplo:

<ItemGroup>
  <DeleteAfterBuild Include="$(OutputPath)Scripts\*.js" Exclude="$(OutputPath)Scripts\*.min.js" />
  <DeleteAfterBuild Include="$(OutputPath)Scripts\MyScripts\*.js" Exclude="$(OutputPath)Scripts\MyScripts\*.min.js" />
  <DeleteAfterBuild Include="$(OutputPath)Content\*.css" Exclude="$(OutputPath)Content\*.min.css" />
</ItemGroup>
<Delete Files="@(DeleteAfterBuild)" />

En nuestra aplicación web vamos a referenciar los scripts de dos formas diferentes, según se trate de la aplicación en modo debug (podríamos decir en desarrollo) o no (en producción):

<%if (HttpContext.Current.IsDebuggingEnabled){%>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
<link href="../../Content/Style1.css" rel="stylesheet" type="text/css" />
<link href="../../Content/Style2.css" rel="stylesheet" type="text/css" />
<script src="../../Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="../../Scripts/ScriptJquery1.js" type="text/javascript"></script>
<script src="../../Scripts/ScriptJquery2.js" type="text/javascript"></script>
<script src="../../Scripts/MyScripts/Script2.js" type="text/javascript"></script>
<script src="../../Scripts/MyScripts/Script1.js" type="text/javascript"></script>
<%} else { %>
<link href="../../Content/AllCss.min.css" rel="stylesheet" type="text/css" />
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="Scripts/AllJs.min.js" type="text/javascript"></script>
<script src="Scripts/MyScripts/Script2.min.js" type="text/javascript"></script>
<script src="Scripts/MyScripts/Script1.min.js" type="text/javascript"></script>
% } %>

Nota: si bien esto es algo molesto de hacer (sobre todo si en cada vista donde referenciamos a un script debemos preguntar por lo mismo), lo podemos solucionar ,por ejemplo, por medio de HTML Helpers o utilizando otro mecanismo que nos automaticen esta tarea.

Finalmente hacemos el “Build” de nuestro nuevo proyecto y validamos que no haya errores:

Compilando el proyecto

Compilando el proyecto

El resultado lo encontramos dentro de la carpeta Release del proyecto:

Proyecto de salida con archivos minimizados.

Proyecto de salida con archivos minimizados.

Comparando un poco los resultados podemos ver cuanto más prolijo y liviano quedan las llamadas a nuestros scripts y hojas de estilos (en la primer imagen veremos los resultados sin minimizar y en la siguiente nuestros archivos “optimizados”):

Aplicación sin archivos minimizados

Aplicación sin archivos minimizados

Aplicación con archivos minimizados

Aplicación con archivos minimizados

Espero que les sea util, y no dejen de ver los otros tipos de configuraciones que nos ofrece los proyectos Web Deployment Project ya que van a encontrar cosas muy interesantes.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s