Как я могу автоматически сжать и свернуть файлы JavaScript в приложении ASP.NET MVC?
Итак, у меня есть приложение 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>
Спасибо
Ответы
Ответ 1
Я лично считаю, что сохранение файлов во время разработки неоценимо и что во время производства это когда-то похожее на это. Поэтому я изменил свое развертывание script, чтобы сделать это выше.
У меня есть раздел, который гласит:
<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>
<% } %>
Конструкция script принимает все файлы в разделе и объединяет их все вместе. Затем я использую YUI minifier, чтобы получить уменьшенную версию javascript. Поскольку это обслуживается IIS, я бы скорее включил сжатие в IIS, чтобы получить сжатие gzip.
**** Добавлено ****
Мое развертывание script - это MSBuild script. Я также использую отличные задачи сообщества MSBuild (http://msbuildtasks.tigris.org/), чтобы помочь развернуть приложение.
Я не буду публиковать весь файл script здесь, но вот некоторые соответствующие строки должны продемонстрировать большую часть того, что он делает.
В следующем разделе будет запущена сборка компилятора asp.net для копирования приложения на целевой диск. (На предыдущем шаге я просто запускаю команды net 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, когда мне нужно развернуть среду.
Ответ 2
На самом деле гораздо проще использовать Проекты веб-развертывания (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
Ответ 3
Скотт Ханзельман недавно написал о комбинирование и перемещение скриптов в статические файлы, в основном используя 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>
Что касается минимизации статических файлов, вам, вероятно, придется (и должен) использовать инструменты для минимизации при создании/развертывании.
Ответ 4
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 также предлагает флаг отладки, который при включении не минимизирует или не объединяет скрипты, когда они установлены, что очень полезно.
В течение нескольких минут я пошел от Yslow от F до B. (24 скрипта до 2)... Удивительно! И падение на 40 килобайт.
Очевидный недостаток - сервер делает сжатие "на лету". Я думаю, что есть варианты кэшировать объединенный script в течение определенного периода, который бы быстро смягчил это, хотя.
Ответ 5
Как и другие, вам лучше всего создать статическую мини-сборку. Кроме того, здесь доступна версия YUICompressor для .NET: http://www.codeplex.com/YUICompressor
Ответ 6
Вы можете использовать MvcContrib.IncludeHandling. Это:
- Поддержка CSS и JS
- Объединяется с одним запросом
- Minifies
- Сжатие Gzip/Deflate
- Устанавливает заголовки кешей
- Использует методы расширения HTMLHelper для регистрации, чтобы затем объединить их во время выполнения
- Подключается через IoC
Под обложками используется YUICompressor.
Ответ 7
Я написал что-то для этого автоматически. Он использует компилятор google закрытия. Вы можете прочитать здесь код:
http://www.picnet.com.au/blogs/Guido/post/2009/12/10/Javascript-runtime-compilation-using-AspNet-and-Googles-Closure-Compiler.aspx
Спасибо
Гвидо
Ответ 8
Я знаю, что это старый вопрос, но он появился первым, так как я выполнял поиск по минимизации. Я бы рекомендовал использовать Gruntjs, http://gruntjs.com. Это полный инструмент создания веб-страниц.