37

所以我有一个 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>

谢谢

4

8 回答 8

24

我个人认为,在开发过程中将文件分开是非常宝贵的,而在生产过程中,这样的事情很重要。因此,我修改了我的部署脚本以执行上述操作。

我有一段内容如下:

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

构建脚本获取该部分中的所有文件并将它们组合在一起。然后我使用 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。

于 2009-08-03T20:04:40.287 回答
8

实际上,使用Web 部署项目(WDP)有一种更简单的方法。WDP 将管理aspnet__compileraspnet__merge工具的复杂性。您可以通过 Visual Studio 内的 UI 自定义该过程。

至于压缩 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>

这使用了我认为基于 JSMin的MSBuild 社区任务中的 JSCompress MSBuild 任务。

这个想法是,让所有 js 文件保持原样(即可调试/人类可读)。当您构建 WDP 时,它将首先将 js 文件复制到OutputPath,然后调用CompressJavascript目标以最小化 js 文件。这不会修改您的原始源文件,只会修改 WDP 项目的输出文件夹中的源文件。然后将文件部署在 WDP 输出路径中,其中包括预编译的站点。我在我的书中介绍了这个确切的场景(我的名字下方的链接)

您也可以让 WDP 处理创建虚拟目录,只需选中一个复选框并填写虚拟目录的名称。

有关 MSBuild 的一些链接:

赛义德·易卜拉欣·哈希米

我的书:Microsoft Build Engine 内部:使用 MSBuild 和 Team Foundation Build

于 2009-08-05T03:15:38.110 回答
4

Scott Hanselman 最近发表了一篇关于将脚本组合和移动到静态文件的博客,基本上是使用ScriptManagerwithCompositeScript引用和Path属性:

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

在缩小静态文件方面,您可能必须(并且应该)在构建/部署时使用缩小工具。

于 2009-08-03T20:02:58.170 回答
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 还提供了一个调试标志,当它打开时不会缩小或组合脚本,这非常有用。

在几分钟之内,我从 F 的 Yslow 分数变为 B。(24 个脚本下降到 2 个)......太棒了!还有一丢丢 40kbs。

明显的缺点是服务器正在动态进行压缩。我认为有一些选项可以在定义的时间段内缓存组合脚本,但这会很快缓解这种情况。

于 2010-05-05T22:53:41.450 回答
2

正如其他人所建议的那样,您最好创建一个静态缩小版本。或者,这里有一个可用于 .NET 的 YUICompressor 版本:http: //www.codeplex.com/YUICompressor

于 2009-08-03T22:16:24.437 回答
2

您可以使用 MvcContrib.IncludeHandling。它:

  • 支持 CSS 和 JS
  • 合并为一个请求
  • 缩小
  • Gzip/Deflate 压缩
  • 设置缓存头
  • 使用 HTMLHelper 扩展方法注册包含,然后在运行时组合它们
  • 可通过 IoC 插拔

在幕后,它使用 YUICompressor。

于 2010-01-14T09:28:06.800 回答
0

我已经写了一些东西来自动为我处理这个问题。它使用谷歌的闭包编译器。你可以在这里阅读代码:

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

谢谢

圭多

于 2009-12-10T03:17:27.333 回答
0

我知道这是一个老问题,但它首先出现在我进行一些缩小搜索时。我会推荐使用 Gruntjs,http ://gruntjs.com 。它是一个完整的 Web 构建工具。

于 2013-11-23T20:26:47.453 回答