Как я могу автоматически сжимать и минимизировать файлы JavaScript в приложении ASP.NET MVC? - PullRequest
36 голосов
/ 03 августа 2009

Итак, у меня есть приложение ASP.NET MVC, которое ссылается на несколько файлов javascript в разных местах (в основной записи сайта и на дополнительные ссылки в нескольких видах).

Я хотел бы знать, существует ли автоматизированный способ сжатия и минимизации таких ссылок в один файл .js, где это возможно. Такой, что этот ...

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

... может быть уменьшено до чего-то подобного ...

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

Спасибо

Ответы [ 8 ]

24 голосов
/ 04 августа 2009

Лично я считаю, что хранение файлов отдельно во время разработки неоценимо и что во время производства имеет значение нечто подобное. Поэтому я изменил свой сценарий развертывания, чтобы сделать это выше.

У меня есть раздел, который гласит:

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

И в моем файле главной страницы я использую:

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

Скрипт сборки берет все файлы в разделе и объединяет их все вместе. Затем я использую Minifier YUI, чтобы получить уменьшенную версию JavaScript. Поскольку это обслуживается IIS, я бы предпочел включить сжатие в IIS, чтобы получить сжатие gzip. **** Добавлено **** Мой скрипт развертывания - это скрипт MSBuild. Я также использую отличные задачи сообщества MSBuild (http://msbuildtasks.tigris.org/), чтобы помочь развернуть приложение.

Я не собираюсь публиковать здесь весь свой файл скрипта, но вот некоторые соответствующие строки, которые должны продемонстрировать большую часть того, что он делает.

В следующем разделе будет запущена сборка в компиляторе asp.net для копирования приложения на целевой диск. (На предыдущем шаге я просто запускаю команды exec net use и подключаю сетевой диск).

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

После того, как все проекты решений скопированы, я запускаю это:

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

Этого должно быть достаточно, чтобы начать работу по автоматизации развертывания. Я поместил все эти вещи в отдельный файл под названием Aspnetdeploy.msbuild. Я просто использую msbuild / t: Target всякий раз, когда мне нужно выполнить развертывание в среде.

8 голосов
/ 05 августа 2009

На самом деле есть гораздо более простой способ использования Web Deployment Projects (WDP). WDP будет управлять сложностями инструмента aspnet__compiler и aspnet__merge . Вы можете настроить процесс с помощью пользовательского интерфейса в Visual Studio.

Что касается сжатия файлов js, вы можете оставить все свои файлы js на месте и просто сжать эти файлы во время процесса сборки. Так что в WDP вы бы объявили что-то вроде этого:

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

Используется задача JSCompress MSBuild из Задачи сообщества MSBuild , которая, как мне кажется, основана на JSMin.

Идея в том, чтобы оставить все ваши js-файлы такими, какие они есть (т.е. отлаживаемые / читабельные) . Когда вы создаете свой WDP, он сначала скопирует js-файлы в OutputPath , а затем вызывается цель CompressJavascript , чтобы минимизировать js-файлы. Это не изменяет ваши исходные файлы, только те, которые находятся в выходной папке проекта WDP. Затем вы развертываете файлы в выходном пути WDP, который включает предварительно скомпилированный сайт. Я описал этот точный сценарий в своей книге (ссылка под моим именем) .

Вы также можете позволить WDP обрабатывать создание виртуального каталога, просто установите флажок и введите имя виртуального каталога.

Для некоторых ссылок на MSBuild:

Сайед Ибрагим Хашими

Моя книга: Внутри Microsoft Build Engine: Использование MSBuild и Team Foundation Build

4 голосов
/ 06 мая 2010

MvcContrib.IncludeHandling хорошо работает в этой ситуации. В этом примере у меня есть модель с коллекцией стилей (строка). Кроме того, если мне нужно добавить собственный стиль / JS на страницу, то можно сделать то же самое. Затем вызов Html.RenderCss объединяет все стили / js в один файл и уменьшает его.

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

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

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

То же самое для 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");
%>

Когда это передается клиенту, вывод выглядит так (минимизированный объединенный 1 файл)

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

API также предлагает флаг отладки, который при включении не минимизирует и не комбинирует сценарии, когда он установлен, что очень полезно.

В считанные минуты я перешел от Ислоу к F (от 24 сценариев до 2) ... Потрясающе! И капля 40кбс.

Очевидным недостатком является то, что сервер выполняет сжатие на лету. Я думаю, что есть опции для кэширования комбинированного сценария на определенный период, который бы быстро это облегчил.

4 голосов
/ 04 августа 2009

Скотт Хансельман недавно написал в блоге о комбинировании и перемещении скриптов в статические файлы , в основном с использованием ScriptManager с CompositeScript ссылками и атрибутом Path:

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

Что касается минимизации статических файлов, вы, вероятно, должны (и должны) использовать минимизирующие инструменты во время сборки / развертывания.

2 голосов
/ 14 января 2010

Вы можете использовать MvcContrib.IncludeHandling. Это:

  • Поддерживает CSS и JS
  • Объединяет в один запрос
  • Minifies
  • сжатие Gzip / Deflate
  • Настройка заголовков кэша
  • Использует методы расширения HTMLHelper для регистрации включений, чтобы затем объединить их во время выполнения
  • Возможность подключения через IoC

Под крышками используется YUICompressor.

2 голосов
/ 04 августа 2009

Как и другие предлагали, вам лучше создать статичную минимизированную сборку. В качестве альтернативы, здесь доступна версия YUICompressor для .NET: http://www.codeplex.com/YUICompressor

0 голосов
/ 24 ноября 2013

Я знаю, что это старый вопрос, но он возник первым, когда я проводил некоторые миниатюрные поиски. Я бы порекомендовал использовать Gruntjs, http://gruntjs.com. Это полноценный инструмент для веб-сборки.

0 голосов
/ 10 декабря 2009

Я написал что-то для этого автоматически. Он использует закрывающий компилятор Google. Вы можете прочитать код здесь:

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

Спасибо

Guido

...