37 votes

Meilleure façon de compresser et de réduire automatiquement les fichiers JavaScript dans une application ASP.NET MVC

J'ai donc une ASP.NET MVC app qui fait référence à un certain nombre de fichiers javascript dans différents endroits (dans le site de maître et d'autres références à plusieurs points de vue).

Je voudrais savoir si il existe un moyen automatisé, et si oui, quelle est l'approche recommandée, pour la compression et à minimiser ces références en une seule .fichier js, si possible. Tels que cette ...

<script src="<%= ResolveUrl("~") %>Content/ExtJS/Ext.ux.grid.GridSummary/Ext.ux.grid.GridSummary.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ExtJS/ext.ux.rating/ext.ux.ratingplugin.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ExtJS/ext-starslider/ext-starslider.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ExtJS/ext.ux.dollarfield.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ExtJS/ext.ux.combobox.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ExtJS/ext.ux.datepickerplus/ext.ux.datepickerplus-min.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ExtJS/SessionProvider.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ExtJS/TabCloseMenu.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ActivityViewer/ActivityForm.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ActivityViewer/UserForm.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ActivityViewer/SwappedGrid.js" type="text/javascript"></script>
<script src="<%= ResolveUrl("~") %>Content/ActivityViewer/Tree.js" type="text/javascript"></script>

... pourrait être réduit à quelque chose comme ça ...

<script src="<%= ResolveUrl("~") %>Content/MyViewPage-min.js" type="text/javascript"></script>

Merci

24voto

Min Points 2712

Personnellement, je pense que garder les fichiers distincts au cours du développement est précieux et qu'au cours de la production, c'est quand quelque chose comme cela compte. J'ai donc modifié mon script de déploiement afin de le faire ci-dessus.

J'ai un article qui se lit comme suit:

<Target Name="BeforeDeploy">

    	<ReadLinesFromFile File="%(JsFile.Identity)">
    		<Output TaskParameter="Lines" ItemName="JsLines"/>
    	</ReadLinesFromFile>

    	<WriteLinesToFile File="Scripts\all.js" Lines="@(JsLines)" Overwrite="true"/>

    	<Exec Command="java -jar tools\yuicompressor-2.4.2.jar Scripts\all.js -o Scripts\all-min.js"></Exec>

    </Target>

Et dans mon fichier de page maître, j'utilise:

if (HttpContext.Current.IsDebuggingEnabled)
   {%>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/jquery-1.3.2.js")%>"></script>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/jquery-ui-1.7.2.min.js")%>"></script>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/jquery.form.js")%>"></script>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/jquery.metadata.js")%>"></script>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/jquery.validate.js")%>"></script>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/additional-methods.js")%>"></script>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/form-interaction.js")%>"></script>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/morevalidation.js")%>"></script>
    <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/showdown.js") %>"></script>
<%
   }  else  {%> 
  <script type="text/javascript" src="<%=Url.UrlLoadScript("~/Scripts/all-min.js")%>"></script>
<% } %>

Le script prend tous les fichiers dans la section et les combine tous ensemble. Puis-je utiliser YUI est minifier pour obtenir une version compacte du javascript. Parce que c'est desservie par IIS, je serais plutôt d'activer la compression dans IIS pour obtenir une compression gzip. ** Ajout de l' ** Mon script de déploiement est un script MSBuild. J'utilise aussi l'excellent MSBuild missions de la communauté (http://msbuildtasks.tigris.org/) pour déployer une application.

Je ne vais pas poster la totalité de mon fichier de script ici, mais voici quelques lignes devraient démontrer la plupart de ce qu'il fait.

La section suivante va exécuter le construire en asp.net compilateur pour copier l'application sur le lecteur de destination. (Dans une étape précédente, je viens de lancer exec net, utiliser les commandes et de mapper un lecteur réseau partagé).

<Target Name="Precompile" DependsOnTargets="build;remoteconnect;GetTime">

     	<MakeDir Directories="%(WebApplication.SharePath)\$(buildDate)" />

     	<Message Text="Precompiling Website to %(WebApplication.SharePath)\$(buildDate)" />

     	<AspNetCompiler
     		VirtualPath="/%(WebApplication.VirtualDirectoryPath)"
     		PhysicalPath="%(WebApplication.PhysicalPath)"
     		TargetPath="%(WebApplication.SharePath)\$(buildDate)"
     		Force="true"
    		Updateable="true"
    		Debug="$(Debug)"
     		/>
     	<Message Text="copying the correct configuration files over" />

     	<Exec Command="xcopy $(ConfigurationPath) %(WebApplication.SharePath)\$(buildDate) /S /E /Y" />

     </Target>

Après tout de la solution de projets sont copiés sur je l'exécute:

    <Target Name="_deploy">
    	<Message Text="Removing Old Virtual Directory" />
    	<WebDirectoryDelete
    		VirtualDirectoryName="%(WebApplication.VirtualDirectoryPath)"
    		ServerName="$(IISServer)"
    		ContinueOnError="true"
    		Username="$(username)"	
    		HostHeaderName="$(HostHeader)"
    		/>

    	<Message Text="Creating New Virtual Directory" />

    	<WebDirectoryCreate 
    		VirtualDirectoryName="%(WebApplication.VirtualDirectoryPath)" 
    		VirtualDirectoryPhysicalPath="%(WebApplication.IISPath)\$(buildDate)"
    		ServerName="$(IISServer)"
    		EnableDefaultDoc="true"
    		DefaultDoc="%(WebApplication.DefaultDocument)"
    		Username="$(username)"
    		HostHeaderName="$(HostHeader)"
    		/>
</Target>

Ce devrait être assez pour vous obtenir a commencé sur l'automatisation du déploiement. J'ai mis tout ça dans un fichier séparé appelé Aspnetdeploy.msbuild. Je viens de msbuild /t:Cible chaque fois que j'ai besoin de déployer un environnement.

8voto

En fait, il ya un moyen beaucoup plus facile à l'aide de Web des Projets de Déploiement (PDEO). Le PDEO va gérer la complexité de l' aspnet__compilateur et aspnet__fusionner outil. Vous pouvez personnaliser le processus par une INTERFACE utilisateur à l'intérieur de Visual Studio.

Comme pour la compression de la js fichiers, vous pouvez laisser tous vos fichiers js en place et de compresser ces fichiers pendant le processus de génération. Ainsi, dans le cadre du PDEO vous pouvez déclarer quelque chose comme ceci:

<Project>
   REMOVE CONTENT HERE FOR WEB

<Import 
  Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<!-- Extend the build process -->
<PropertyGroup>
  <BuildDependsOn>
    $(BuildDependsOn);
    CompressJavascript
  </BuildDependsOn>
</PropertyGroup>

<Target Name="CompressJavascript">
  <ItemGroup>
    <_JSFilesToCompress Include="$(OutputPath)Scripts\**\*.js" />
  </ItemGroup>
  <Message Text="Compresing Javascript files" Importance="high" />
  <JSCompress Files="@(_JSFilesToCompress)" />
</Target>
</Project>

Il utilise la JSCompress tâche MSBuild de la MSBuild missions de la Communauté, qui, je pense, est basé hors de JSMin.

L'idée est de laisser tous vos fichiers js comme ils sont (c'est à dire debuggable/lisible par un humain). Lorsque vous construisez votre PDEO, il va d'abord copier les fichiers js à la OutputPath et puis le CompressJavascript cible est appelé à minimiser les fichiers js. Cela ne modifie pas vos fichiers source d'origine, seulement ceux dans le dossier de sortie du PDEO projet. Puis vous déployez les fichiers dans le WDPs chemin de la sortie, qui comprend le pré-compilied site. J'ai couvert ce scénario exact dans mon livre (lien au-dessous de mon nom).

Vous pouvez également laisser le PDEO poignée de créer le Répertoire Virtuel ainsi, il suffit de cocher une case et saisissez le nom du répertoire virtuel.

Pour certains liens sur MSBuild:

4voto

Josef Pfleger Points 37003

Scott, Hanselman récemment blogué sur la combinaison et le déplacement des scripts pour les fichiers statiques, essentiellement à l'aide de l' ScriptManager avec CompositeScript références et un Path d'attribut:

<asp:ScriptManager runat="server">
    <CompositeScript path="http://www.example.com/1.js">
    	<Scripts>
    		<asp:ScriptReference />
    		<asp:ScriptReference />
    		<!-- etc. -->
    	</Scripts>
    </CompositeScript>
</asp:ScriptManager>

En termes de minifying les fichiers statiques, vous avez probablement (et doit) utiliser les minifying des outils lors de la compilation/déploiement.

4voto

Jafin Points 1401

MvcContrib.IncludeHandling fonctionne bien pour cette situation. Dans l'exemple, j'ai un Modèle avec une collection de styles de caractères (string). Aussi, si j'ai besoin d'ajouter un Style personnalisé/JS de la page, puis peut le faire aussi bien. Puis l'appel de Html.RenderCss combine tous les styles/js dans un fichier et minifies il.

<head>
<% foreach (var styleSheet in Model.Styles) {%>
<% Html.IncludeCss(styleSheet)); 

<% } %>
<% Html.IncludeCss("~/Scripts/jquery.1.4.2.js")); 

<%= Html.RenderCss() %>
</head>

Même façon pour le javascript.

<%
Html.IncludeJs("~/scripts/ConsoleLogger.js");
Html.IncludeJs("~/scripts/jquery.log.js");
Html.IncludeJs("~/Scripts/2010.1.416/jquery.validate.min.js");
Html.IncludeJs("~/Scripts/2010.1.416/telerik.calendar.min.js");
Html.IncludeJs("~/Scripts/2010.1.416/telerik.datepicker.js");
Html.IncludeJs("~/scripts/jquery.ui.datepicker-en-GB.js");
%>

<%=Html.RenderJs()%>

Quand c'est rendu au client la sortie ressemble à ceci (minifiés combiné 1 fichier)

<link rel='stylesheet' type='text/css' href='http://stackoverflow.com/include/css/-QdUg9EnX5mpI0e4aKAaOySIbno%40'/>

L'API propose également un indicateur de débogage qui, lorsqu'il n'est pas rapetisser ou de combiner les scripts en jeu, ce qui est très utile.

En quelques minutes, je suis passé de Yslow score de F B. (24 scripts à 2)... Génial! Et une goutte de 40kbs.

Évident inconvénient est que le serveur est en train de faire de la compression à la volée. Je pense qu'il y a des options pour mettre en cache le combiné script pour une période définie qui permettrait de soulager rapidement de cette même si.

2voto

Evan Trimboli Points 15857

Comme d'autres l'ont suggéré, vous feriez mieux de créer une version statique réduite. Alternativement, il existe une version de YUICompressor disponible pour .NET ici: http://www.codeplex.com/YUICompressor

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X