如何在 ASP.NET MVC 应用程序中自动压缩和最小化 JavaScript 文件?

发布于 2024-07-30 05:20:58 字数 1883 浏览 12 评论 0原文

因此,我有一个 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>

谢谢

So I have an ASP.NET MVC app that references a number of javascript files in various places (in the site master and additional references in several views as well).

I'd like to know if there is an automated way for compressing and minimizing such references into a single .js file where possible. Such that this ...

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

... could be reduced to something like this ...

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

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

尬尬 2024-08-06 05:20:58

Scott Hanselman 最近在博客中介绍了将脚本组合并移动到静态文件,基本上使用 ScriptManager 与 < code>CompositeScript 引用和 Path 属性:

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

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

Scott Hanselman recently blogged about combining and moving scripts to static files, basically using the ScriptManager with CompositeScript references and a Path attribute:

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

In terms of minifying the static files, you probably have to (and should) use minifying tools at build/deployment time.

醉梦枕江山 2024-08-06 05:20:58

我个人认为,在开发过程中将文件分开是非常有价值的,而在生产过程中这样的事情就很重要。 因此,我修改了部署脚本以实现上述目的。

我有一个部分内容如下:

<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 的 minifier 来获取 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 。

I personally think that keeping the files separate during development is invaluable and that during production is when something like this counts. So I modified my deployment script in order to do that above.

I have a section that reads:

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

And in my master page file I use:

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

The build script takes all the files in the section and combines them all together. Then I use YUI's minifier to get a minified version of the javascript. Because this is served by IIS, I would rather turn on compression in IIS to get gzip compression.
**** Added ****
My deployment script is an MSBuild script. I also use the excellent MSBuild community tasks (http://msbuildtasks.tigris.org/) to help deploy an application.

I'm not going to post my entire script file here, but here are some relevant lines to should demonstrate most of what it does.

The following section will run the build in asp.net compiler to copy the application over to the destination drive. (In a previous step I just run exec net use commands and map a network share drive).

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

After all of the solution projects are copied over I run this:

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

That should be enough to get you started on automating deployment. I put all this stuff in a separate file called Aspnetdeploy.msbuild. I just msbuild /t:Target whenever I need to deploy to an environment.

画▽骨i 2024-08-06 05:20:58

实际上,有一种更简单的方法,使用 网络部署项目 (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>

这使用了我在 MSBuild 社区任务 中的 JSCompress MSBuild 任务。 think 是基于 JSMin 的。

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

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

有关 MSBuild 的一些链接:

Sayed Ibrahim Hashimi

我的书:Microsoft 构建引擎内部:使用 MSBuild 和 Team Foundation Build

Actually there is a much easier way using Web Deployment Projects (WDP). The WDP will manage the complexities of the aspnet__compiler and aspnet__merge tool. You can customize the process by a UI inside of Visual Studio.

As for the compressing the js files you can leave all of your js files in place and just compress these files during the build process. So in the WDP you would declare something like this:

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

This uses the JSCompress MSBuild task from the MSBuild Community Tasks which I think is based off of JSMin.

The idea is, leave all of your js files as they are (i.e. debuggable/human-readable). When you build your WDP it will first copy the js files to the OutputPath and then the CompressJavascript target is called to minimize the js files. This doesn't modify your original source files, just the ones in the output folder of the WDP project. Then you deploy the files in the WDPs output path, which includes the pre-compilied site. I covered this exact scenario in my book (link below my name).

You can also let the WDP handle creating the Virtual Directory as well, just check a checkbox and fill in the name of the virtual directory.

For some links on MSBuild:

Sayed Ibrahim Hashimi

My Book: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build

找个人就嫁了吧 2024-08-06 05:20:58

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 个)...太棒了! 还有 40kb 的下降。

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

MvcContrib.IncludeHandling works well for this situation.
In the example, I have a Model with a collection of styles (string).
Also if I need to add a custom Style/JS to the page then can do that as well.
Then calling Html.RenderCss combines all the styles/js together in one file and minifies it.

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

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

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

Same way for 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");
%>

When this gets rendered to the client the output looks like this (minified combined 1 file)

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

The API also offers a debug flag which when on doesn't minify or combine the scripts when set which is greatly useful.

In a matter of minutes I went from Yslow score of F to B. (24 scripts down to 2)... Awesome! And a drop of 40kbs.

Obvious downside is the server is doing the compression on the fly. I think there are options to cache the combined script for a defined period which would quickly alleviate this though.

作妖 2024-08-06 05:20:58

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

As others have suggested, you'd be best off creating a static minified build. Alternatively, there's a version of YUICompressor available for .NET here: http://www.codeplex.com/YUICompressor

揽月 2024-08-06 05:20:58

您可以使用 MvcContrib.IncludeHandling。 它:

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

在幕后,它使用 YUICompressor。

You could use MvcContrib.IncludeHandling. It:

  • Supports CSS and JS
  • Combines to a single request
  • Minifies
  • Gzip/Deflate compresses
  • Sets up cache headers
  • Uses HTMLHelper extension methods to register includes to then combine them at run-time
  • Is pluggable via IoC

Under the covers, it uses YUICompressor.

失眠症患者 2024-08-06 05:20:58

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

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

谢谢

Guido

I have written something to handle this for me automatically. It uses google's closure compiler. You can read the code here:

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

Thanks

Guido

趁年轻赶紧闹 2024-08-06 05:20:58

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

I know this is an old question, but it came up first as I was doing some minification searches. I would recommend using Gruntjs, http://gruntjs.com. It is a complete web build tool.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文