65.9K
CodeProject 正在变化。 阅读更多。
Home

自动压缩、合并、优化和缓存 ASP.NET 项目中的 *.js 和 *.css 文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.74/5 (16投票s)

2009年2月23日

CPOL

5分钟阅读

viewsIcon

159723

downloadIcon

3155

自动压缩、合并、优化和缓存 ASP.NET 项目中的 .js 和 .css 文件

引言

本文将向您展示如何优化 ASP.NET Web 应用程序中的样式表和 JavaScript 文件。更具体地说,您将了解到 ASP.NET Web 应用程序中的所有样式表和 JavaScript 文件都可以自动进行压缩、优化、合并和缓存。

背景 

每次在网页中使用 script 或 link 标签引用 JavaScript 或样式表文件时,浏览器都会发出一个单独的请求来获取该文件。这会导致大量的网络延迟。更有效的方法是只发送一个请求来获取所有 JavaScript 文件,另一个请求来获取页面上所有脚本文件。我通过使用一个 HTTP 处理程序来实现这一点,该处理程序将返回每组脚本或样式表文件所需的内容。这些内容还将在浏览器和服务器上进行压缩、优化和缓存,并包含正确的文件依赖关系,以便对文件的任何更改都会使客户端和服务器缓存失效。

我想感谢 **Moiz Dhanji** 的 文章

我使用了他提供的许多代码来开发这个项目。我主要增加的功能包括处理 CSS 文件、文件依赖缓存以及用于轻松移植到其他项目的自定义控件。主要移除的功能是性能分析器以及处理嵌入式资源文件的能力。

我知道 Ajax 工具包的 ScriptManager 控件可以合并脚本文件,这可能适合您的需求,但它只会合并它们。我的项目除了合并之外,还可以对其进行压缩、优化和缓存。我的项目还可以处理 CSS 文件。此外,ScriptManager 会强制您下载所有 ASP.NET Ajax 脚本文件,而您可能不需要它们。

实施

为 Web.config 创建了节

ScriptCombinerSection 类完成了这项工作。它基本上与 Moiz Dhanji 的代码相同,只是删除了一些不必要的属性。

创建了自定义处理程序

CssJscriptOptimizerHandler 类执行项目的主要功能。它负责文件的压缩、优化、合并和缓存。

创建了自定义控件

ScriptCombinerStyleSheetCombiner 控件分别负责检查其包含的脚本和链接标签,然后渲染指向自定义处理程序的相应单一请求 URL 以进行处理。

路径,路径,路径

我为这个项目设定的另一个目标是让它对脚本和样式表开发人员透明。我不想让他们以任何方式修改他们现有的工作方式来配合我。关于 CSS 的一件事是有一个 URL 属性。这个属性没有 ASP.NET 所具有的应用程序根目录 (~) 的概念。因此,很多时候,文件中有相对路径,如“../Images/image1.jpg”。如果处理程序与 CSS 文件不在同一个目录中,这就会出错。为了解决这个问题,我在自定义处理程序中实现了一个 FixUrlPaths 方法,当它看到 URL 属性时,会计算出正确的路径。

如何使用

web.config 文件中

  1. configSections 元素中,添加
     <section name="optimizerSection" 
              type="CnCssJscriptOptimizer.ConfigurationSections.OptimizerSection,   
     CnCssJscriptOptimizer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  2. configuration 元素中,添加 optimizerSection。例如:
            <optimizerSection
              enable="true"
              enableScriptCompression="true"
              enableSheetCompression="true"
              enableScriptMinification="true"
              enableSheetMinification="true"
              fullHandlerPath="~/CnScriptResource.ashx"
              >
                <add key="1" path="~/Scripts/Script01.js" />
                <add key="2" path="~/Scripts/Script02.js" />
                <add key="3" path="~/Scripts/Script03.js" />
                <add key="4" path="~/Styles/test1.css" />
                <add key="5" path="~/Styles/test2.css" />
                <add key="6" path="~/Styles/test3.css" />
            </optimizerSection>

    其中 fullHandlerPath 是指向您的 httphandler 名称的路径,该处理程序继承自 CssJscriptOptimizerHandler,并且 key 是任何任意且 URL 友好的唯一 key 值,而 path 是您项目中脚本或 CSS 文件的路径。请注意,您希望在项目中“C4”(Combine, Compress, Cache, Concatenate)的所有脚本和 CSS 文件都应在此列出。另外请注意,所有路径都应以“~”开头。
    请注意,设置 enable="false" 属性将禁用优化器。

  3. 为您的 Web 项目创建一个新的处理程序文件。让它继承自 CssJscriptOptimizerHandler。该文件的路径应在 optimizerSectionfullHandlerPath 属性中指定。
  4. 通过以下方式在您的 *.aspx*.ascx 和/或 *.master 文件中注册控件:
       <%@ Register Assembly="CnCssJscriptOptimizer" 
    	Namespace="CnCssJscriptOptimizer.Controls" TagPrefix="cc1" %>
  5. 在您的 *.aspx 文件中,将 StyleSheetCombiner ScriptCombiner 控件标签放在您的 CSS 和脚本声明周围。例如:
    <cc1:StyleSheetCombiner ID="sheetCombiner" runat="server">
    <link rel="stylesheet" href="Styles/test1.css" />
    <link rel="stylesheet" href="Styles/test1.css" />
    <link rel="stylesheet" href="Styles/test1.css" />
    <link rel="stylesheet" href="Styles/test1.css" />
    <link rel="stylesheet" href="Styles/test1.css" />
    <link rel="stylesheet" href="Styles/test1.css" />
    <link rel="stylesheet" href="Styles/test1.css" />
    <link rel="stylesheet" href="Styles/test1.css" />
    <link rel="stylesheet" 
    	href='<%# sheetCombiner.ResolveUrl("~/Styles/test2.css")%>' />
    <link rel="stylesheet" 
    	href='<%# sheetCombiner.ResolveUrl("~/Styles/test3.css")%>' />
    	
    </cc1:StyleSheetCombiner>       
    	
    <cc1:ScriptCombiner ID="scriptCombiner" runat="server">
    
    <script src='<%# scriptCombiner.ResolveUrl("~/Scripts/Script01.js")%>' 
            type="text/javascript"></script>
    <script src='<%# scriptCombiner.ResolveUrl("~/Scripts/Script02.js")%>' 
            type="text/javascript"></script>
    <script src="Scripts/Script03.js" type="text/javascript"></script>
    
    </cc1:ScriptCombiner>

    注意:不要使用 <%= controlName.ResolveUrl("~/someUrl")%>,,而是使用数据绑定版本 <%# controlName.ResolveUrl("~/someUrl")%>controlName.DataBind() 会在控件内部被调用。

    如果您的任何样式表链接使用了 media 或 title 属性,那么您可能不希望将它们包含在 StyleSheetCombiner 控件中,因为这些属性会丢失,导致 CSS 渲染不正确。

性能

这是优化器启用时的截图

OptimizerEnabled.JPG

请注意上图,有两个请求被发送到 ResoureHandler.ashx。第一个请求用于获取所有样式表。第二个请求用于检索所有 JavaScript 文件。两个请求的总响应时间(从我缓慢的开发机器和服务器)为 2038 毫秒。

这是未启用优化器时的截图

NoOptimizer.JPG

在上图中,请注意,每个脚本和样式表文件都会发出一个单独的请求。获取所有文件的总响应时间超过 6000 毫秒。现在我知道文件在这种情况下没有被 zip(开发服务器上没有 zip 功能),并且这个总数也可能具有误导性,因为 Web 服务器可能在多个线程上处理这些请求,但我相信大多数浏览器最多只能同时处理两个请求。因此,我认为可以安全地说,在大多数情况下,优化器确实提供了性能改进。您需要自己在一个环境中进行尝试并自行查看。优化器肯定会减少客户端访问您的网站以获取每个页面的次数。

结论

本文向您展示了如何通过自动压缩、合并、优化和缓存 ASP.NET 应用程序中的 JavaScript 和 CSS 文件来优化它们。代码库以及一个示例测试 Web 应用程序已提供给您。祝您编码愉快。

历史

  • 2009 年 2 月 23 日:初次发布
  • 2009 年 3 月 2 日:更新了下载文件
  • 2010 年 3 月 24 日:更新了下载文件
© . All rights reserved.