zoukankan      html  css  js  c++  java
  • Combres库 学习小结以及部分源码分析

         昨天看到有博客园网友发布了一篇关于《使用Combres 库 ASP.NET 网站优化》的文章,觉得是个挺不错的脚本优化的类库,而且目前我的项目公务员考试应战平台也有使用到Js以及css合并压缩优化的技术,想看看能不能借鉴下里面的元素。

    一、Combres介绍

    这里不多做介绍,可以参看http://www.cnblogs.com/shanyou/archive/2010/04/03/1703597.html的链接。

    二、如何使用

    1. 在Combres官方源码中我们找到combres.xsd, 它在\Source\Combres\Combres\Resources下面,这个XML Schema配置在VS.NET开发环境中,可以产生智能提示,具体操作:将文件放入C:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas,并且在VS工具中的工具栏中Xml –> Schemas…中选中该xsd,即可产生智能提示。

    2. 创建一个管理css,js的xml配置文件:

    代码
    <resourceSets url="~/combres.axd" 
                   defaultDuration
    ="30" 
                   defaultVersion
    ="auto"> 
        
    <resourceSet name="siteCss" type="css"> 
          
    <resource path="~/App_Themes/Default/default.css"/> 
        
    </resourceSet> 
      
    </resourceSets>

    其中defaultDuration为缓存过期天数,具体代码可参考:

    cache.SetMaxAge(ResourceSet.DurationInDays);

    其中defaultDebugEnabled默认是否调试,默认为false;如果为true时,可以看到default.css不压缩,不返回304的Http Code(304代表客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用)

    3. 对debugEnabled="false" ,compressionEnabled="true" (compressionEnabled默认为true)配合来使用

    代码
    <combres xmlns="urn:combres"> 
      
    <resourceSets url="~/combres.axd" 
                     defaultDuration
    ="30" 
                     defaultVersion
    ="auto" 
                     defaultDebugEnabled
    ="true"> 
        
    <resourceSet name="siteCss" type="css" debugEnabled="false" compressionEnabled="true"> 
          
    <resource path="~/App_Themes/Default/default.css"/> 
          
    <resource path="~/App_Themes/Default/style.css"/> 
        
    </resourceSet> 
        
    <resourceSet name="siteJs" type="js"> 
          
    <resource path="~/App_Script/jquery-1.3.2.js"/> 
        
    </resourceSet> 
      
    </resourceSets> 
    </combres> 

     如果resourceSets 设置了defaultDebugEnabled="true",那么它的所有resourceSet默认情况都不进行脚本合并和压缩

    image

    只有resourceSet显示设置属性debugEnabled="false",方可进行脚本合并和压缩。

    image

    4. resource的mode属性(dynamic和static):当引用全名路径时,必须使用dynamic:如<resource path=http://localhost:35229/Web/App_Script/jquery-1.3.2.js mode="dynamic"/>,如果使用static将会报错

    image

    具体代码可参考:

    var path = resource.Mode == ResourceMode.Dynamic 
                                   
    ? resource.Path.ToAbsoluteUrl() 
                                   : resource.Path.ResolveUrl();

     可以看出实际上Mode为Dynamic时,可取出绝对路径。

    5. 各个配置节点下还包含 defaultCssMinifierRef和defaultJSMinifierRef的脚本缩小器引用,Combres里面具有内置的一些缩小器,比如

    MSAjaxJSMinifier(MS Ajax Minifier library (http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34488))

    ClosureJSMinifier(Google Closure Compiler (http://closure-compiler.appspot.com/))

    YuiCssMinifier(YUI Compressor library (http://yuicompressor.codeplex.com/))

    YuiJSMinifier(YUI Combression library (http://yuicompressor.codeplex.com/))

    NullMinifier(不做任何处理,直接返回文本)

    缩小器属性默认都为default,让我们看下其中一段代码:

    代码
    public static class Minifier 
            { 
                
    private static readonly XElement[] EmptyParamList = new XElement[0]; 

                
    public static readonly MinifierInfo Off = new MinifierInfo 
                                                        { 
                                                            Name 
    = "off"
                                                            Type 
    = typeof(NullMinifier), 
                                                            BinderType 
    = Binder.Type, 
                                                            Parameters 
    = EmptyParamList 
                                                        }; 

                
    public static readonly MinifierInfo JS = new MinifierInfo 
                                                        { 
                                                            Name 
    = "default"
                                                            Type 
    = typeof(YuiJSMinifier), 
                                                            BinderType 
    = Binder.Type, 
                                                            Parameters 
    = EmptyParamList 
                                                        }; 

                
    public static readonly MinifierInfo Css = new MinifierInfo 
                                                        { 
                                                            Name 
    = "default"
                                                            Type 
    = typeof(YuiCssMinifier), 
                                                            BinderType 
    = Binder.Type, 
                                                            Parameters 
    = EmptyParamList 
                                                        }; 
            }

     说明默认的时候是采用YuiJSMinifier以及YuiCssMinifier缩小器进行压缩。压缩算法分别采用Yahoo.Yui.Compressor.dll中JavaScriptCompressor和CssCompressor类中的Compress方法。

    (另附:Microsoft Ajax缩小器支持2个级别的缩小:常规级,以及超级压扁(hypercrunched)级。开发人员在使用常规级缩小时,Microsoft Ajax缩小器将除去所有不必要的空白,注释,花括号以及分号,在启用超级压扁(hypercrunched)级时,Microsoft Ajax缩小器会通过缩小代码局部变量名称,除去调用不到(unreachable)的代码等方式来全力减小JavaScript文件大小。
    Microsoft Ajax缩小器下载包含了下述组件:

    ajaxmin.exe——缩小JavaScript文件的命令行工具
    ajaxmintask.dll——在Visual Studio项目中缩小JavaScript文件的MSBuild任务
    ajaxmin.dll——可用在C# 或 VB.NET 应用中缩小JavaScript文件的组件)

    6. 配置节点defaultVersionGenerator,作为版本生成器,浏览页面时,将产生这样的地址如:

    /Web/combres.axd/siteCss/-1545244924,“1545244924”就是生成出来的版本,默认设置为“Combres.VersionGenerators.HashCodeVersionGenerator”,还可以设置为“Combres.VersionGenerators.Sha512VersionGenerator”,HashCodeVersionGenerator算法返回的是一个整型数值,实际上也是从GetHashCode()优化出来的数值;Sha512VersionGenerator算法返回的是一个64位的hash值。

    image

    HashCodeVersion生成器

    image

    Sha512Version生成器

    7. localChangeMonitorInterval和remoteChangeMonitorInterval:作为监控是否有刷新资源文件的配置,有个.net提供的类FileSystemWatcher对修改的资源文件去判断是否更新,如果更新过去刷新配置,具体实现没有看明白。

    8. Fasterflect(A Fast and Simple Reflection API(http://fasterflect.codeplex.com/)),Combres这里运用了一个快速反射的开源组件,详细请参考原链接。

    9. dotless.Core(http://www.dotlesscss.com/

    代码
    /**/ .rule1 {font-size: 4px;} /**/ 
    /**/ 
    .rule2 
    {font-size: 4px;} 
    /**/ 
    /* */ 
    /* comment */ 
    /* 

    comment 

    */ 
    body 
    { 
        font-size
    : 4px; 
    } 

    /** Variables **/ 
    @brand_color: #4D926F; 
    #header 
    { 
      color
    : @brand_color; 
    } 
    h2 
    { 
      color
    : @brand_color; 
    } 

    /** Mixins **/ 
    .rounded_corners 
    { 
      -moz-border-radius
    : 8px; 
      -webkit-border-radius
    : 8px; 
      border-radius
    : 8px; 
    } 
    #header 
    { 
      .rounded_corners; 
    } 
    #footer 
    { 
      .rounded_corners; 
    } 

    /** Operations **/ 
    @the-border: 1px; 
    @base-color: #111; 
    #header 
    { 
      color
    : @base-color * 3; 
      border-left
    : @the-border; 
      border-right
    : @the-border * 2; 
    } 
    #footer 
    { 
      color
    : (@base-color + #111) * 1.5; 
    } 

    /** Nested Rules **/ 
    #header 
    { 
      color
    : red; 
      a { 
           font-weight
    : bold; 
           text-decoration
    : none; 
        
    } 
    }

     这个css样式“模版”实现很有意思,通过这种“非正规”并且“变量取法”的程序员习惯的写法,利用dotless.Core.dll组件进行解码,生成一个真正的css样式。官方代码中的css文件带.css.less后缀的名称,其实也可以定义自己的后缀名称。

    10. 我们看到官方代码中有行代码:<cr:Include ID="cr" runat="server" SetName="siteJs" HtmlAttributes="a|b|c|d" />

    这里用到了一个用户控件,查看它的输出呈现代码:

    代码
    protected override void Render(HtmlTextWriter writer) 

        
    if (string.IsNullOrEmpty(HtmlAttributes)) 
        { 
            writer.Write(WebExtensions.CombresLink(SetName)); 
        } 
        
    else 
        { 
            var attributes 
    = new Dictionary<stringstring>(); 
            var array 
    = HtmlAttributes.Split('|'); 
            
    for (int i = 0; i < array.Length; i += 2
            { 
                attributes[array[i]] 
    = array[i + 1]; 
            } 
            writer.Write(WebExtensions.CombresLink(SetName, attributes)); 
        } 


     通过转换在页面上可以得到这样的源文件:<script type="text/javascript" src="/combres.axd/siteJs/-1949545824" a="b" c="d"></script>

    11. global.asax的路径路由功能:

    在Global.asax配置RouteTable.Routes.AddCombresRoute("Combres");并且项目添加引用:System.Web.Routing.dll,修改web.config相关UrlRouting配置节点。

    查看相关的代码:

    代码
    public static void AddCombresRoute(this RouteCollection routes, string name) 
            { 
                var url 
    = Configuration.GetCombresUrl(); 
                var adjustedUrl 
    = url.Substring(2); // Remove the "~/" 
                routes.Add(name, new Route(adjustedUrl + "/{name}/{version}", 
                                           
    new CombresRouteHandler())); 
            }

    这里添加了一个路由映射,通过CombresRouteHandler类进行路由处理,查看该代码:

    代码
    internal sealed class CombresRouteHandler : IRouteHandler 

        
    public IHttpHandler GetHttpHandler(RequestContext requestContext) 
        { 
            var name 
    = requestContext.RouteData.Values["name"as string
            var version 
    = requestContext.RouteData.Values["version"as string
            
    return new CombresHandler(name, version); 
        } 
    }

    其中CombresHandler将执行ProcessRequest方法:

    代码
    public void ProcessRequest(HttpContext context) 

        
    if (context == null
            
    return
        var settings 
    = Configuration.GetSettings(); 
        
    try 
        { 
            
    new RequestProcessor(context, settings, setName, version).Execute(); 
        } 
        
    catch (ResourceSetNotFoundException ex) 
        { 
            NotFound(context, ex); 
        } 
        
    catch (ResourceNotFoundException ex) 
        { 
            NotFound(context, ex); 
        } 
    }

     最核心的就是黑体的部分,其中setName就是文件配置中资源节点的name名称,version就是节点的版本号,Execute方法具体将调用Workflow.Execute()
    public void Execute()
    {
        using (new Timer("Processing " + ResourceSet.Name, Log.IsDebugEnabled, Log.Debug))
        {
            Workflow.Execute();
        }
    }

    Workflow实际是一个接口,它的实现为DefaultProcessingWorkflow以及DebugProcessingWorkflow,其中DefaultProcessingWorkflow对资源路径中的内容进行缓存处理,注意看到Execute()方法,方法作为IProcessingWorkflow的接口方法,具体实现中调用方法processor.WriteFromServerCache(),从WriteFromServerCache方法进行缓存处理。

    暂时先分析到这里,很多细节上没有去细看,等有空再写篇比较深入点的文章:)

    最后附上我测试时用的源代码:CombresSolution.rar

  • 相关阅读:
    我该不该学习C语言
    Java入门系列-27-反射
    Java入门系列-26-JDBC
    Java入门系列-25-NIO(实现非阻塞网络通信)
    Java入门系列-24-实现网络通信
    Java入门系列-23-NIO(使用缓冲区和通道对文件操作)
    Java入门系列-22-IO流
    Java入门系列-21-多线程
    Java入门系列-20-异常
    Java入门系列-19-泛型集合
  • 原文地址:https://www.cnblogs.com/liping13599168/p/1704154.html
Copyright © 2011-2022 走看看