Pergunta

Então, eu tenho um aplicativo ASP.NET MVC que faz referência a um número de arquivos javascript em vários lugares (no mestre de local e referências adicionais em vários pontos de vista também).

Eu gostaria de saber se existe uma maneira automatizada para comprimir e minimizar tais referências em um único arquivo .js sempre que possível. De tal forma que este ...

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

... poderia ser reduzida para algo como isto ...

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

Graças

Foi útil?

Solução

Eu pessoalmente acho que manter os arquivos separados durante o desenvolvimento é inestimável e que durante a produção é quando algo como isso conta. Então eu modifiquei meu script de implantação, a fim de fazer isso acima.

Eu tenho uma seção que diz:

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

E em meu mestre uso do arquivo de página I:

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>
<% } %>

O script de construção leva todos os arquivos da seção e combina-los todos juntos. Então eu uso minifier do YUI para obter uma versão minified do javascript. Porque este é servido por IIS, eu preferiria ativar a compactação no IIS para obter compressão gzip. **** Adicionado **** Meu script de implantação é um script MSBuild. Eu também uso os excelentes tarefas comunitárias MSBuild ( http://msbuildtasks.tigris.org/ ) para um ajudar a implantar aplicação.

Eu não estou indo para postar todo o meu arquivo script aqui, mas aqui estão algumas linhas relevantes para deveria demonstrar mais do que ele faz.

A seção seguinte irá executar a construção em asp.net compilador para copiar o aplicativo até a unidade de destino. (Em uma etapa anterior eu apenas executar comandos net use exec e mapear uma unidade de compartilhamento de rede).

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

Depois de todos os projetos de solução são copiados eu executar este:

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

Isso deve ser suficiente para você começar em automatizar a implantação. Eu coloquei tudo isso em um arquivo separado chamado Aspnetdeploy.msbuild. Eu só msbuild / t:. Alvo sempre que eu preciso para implantar em um ambiente

Outras dicas

Na verdade, há uma maneira muito mais fácil usando (WDP) Projetos de implantação da web . O WDP irá gerenciar as complexidades do aspnet__compiler e aspnet__merge ferramenta. Você pode personalizar o processo por um interior UI de Visual Studio.

Quanto aos comprimir os arquivos js que você pode deixar todos os seus arquivos js no lugar e apenas comprimir esses arquivos durante o processo de construção. Assim, no WDP você declarar algo como isto:

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

Este usa a tarefa JSCompress MSBuild dos MSBuild Comunidade que eu acho que é baseado fora de JSMin.

A idéia é, deixar todos os seus arquivos js como eles são (i. Debuggable / legível) . Quando você construir seu WDP primeiro irá copiar os arquivos JS para o OutputPath e, em seguida, o CompressJavascript alvo é chamado para minimizar os arquivos js. Isso não modificar seus arquivos fonte original, apenas os na pasta do projeto WDP saída. Em seguida, você implantar os arquivos no caminho de saída WDPs, que inclui o sítio pré-compilied. Eu cobri este cenário exato em meu livro (link abaixo meu nome) .

Você também pode deixar a alça WDP criação do Virtual Directory, bem, basta verificar a caixa de seleção e preencha o nome do diretório virtual.

Para alguns links em MSBuild:

Sayed Ibrahim Hashimi

My Book: Dentro do Microsoft Build Motor: Usando MSBuild e Team Foundation Build

Scott Hanselman recentemente um blog sobre combinar e scripts de se mudar para arquivos estáticos , basicamente, usando ScriptManager com referências CompositeScript e uma Path atributo:

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

Em termos de minifying os arquivos estáticos, você provavelmente terá que (e deve) tempo de uso ferramentas minifying em build / implantação.

MvcContrib.IncludeHandling funciona bem para esta situação. No exemplo, eu tenho um modelo com uma coleção de estilos (string). Além disso, se eu preciso adicionar um costume Estilo / JS para a página, em seguida, pode fazer isso também. Em seguida, chamar combina Html.RenderCss todos os estilos / js juntos em um arquivo e minifies-lo.

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

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

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

Da mesma forma para 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");
%>

Quando isso é renderizado para o cliente a aparência de saída como este (minified combinado 1 arquivo)

<link rel='stylesheet' type='text/css' href='/include/css/-QdUg9EnX5mpI0e4aKAaOySIbno%40'/>

A API também oferece um sinalizador de depuração que, quando em não apoucar ou combinar os scripts quando definido que é muito útil.

Em questão de minutos, eu fui de Yslow marcar de F para B. (24 roteiros para baixo a 2) ... Incrível! E uma gota de 40kbs.

desvantagem óbvia é o servidor está fazendo a compressão na mosca. Eu acho que existem opções para armazenar em cache o script combinado por um período definido que seria rapidamente aliviar este embora.

Como já foi sugerido, você seria melhor fora de criar uma compilação estática minified. Como alternativa, há uma versão de YUICompressor disponível para .NET aqui: http://www.codeplex.com/YUICompressor

Você pode usar MvcContrib.IncludeHandling. -Lo:

  • Suporta CSS e JS
  • combina para uma única solicitação
  • minifies
  • Gzip / Deflate compressas
  • Configura cabeçalhos de cache
  • Usa métodos de extensão HtmlHelper a registar inclui, em seguida, combiná-los em tempo de execução
  • É conectável via IoC

Nos bastidores, ele usa YUICompressor.

Eu escrevi algo para lidar com isso automaticamente para mim. Ele usa compilador fechamento do Google. Você pode ler o código aqui:

http://www.picnet.com.au/blogs/Guido/post/2009/12/10/Javascript-runtime-compilation-using-AspNet-and-Googles-Closure-Compiler aspx

Graças

Guido

Eu sei que isto é uma questão de idade, mas ele veio pela primeira vez como eu estava fazendo algumas pesquisas minification. Eu recomendaria usar Gruntjs, http://gruntjs.com . É uma ferramenta completa de construção web.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top