欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

web优化之-Asp.net MVC js、css动态合并 动态压缩

程序员文章站 2022-03-09 21:25:50
上次写了两篇有关js的合并压缩如 web优化之-m js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载 web优化之-.net js延迟加载 js动态合并 js动态压缩 看了一下的访问...

上次写了两篇有关js的合并压缩如
web优化之-m js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载
web优化之-.net js延迟加载 js动态合并 js动态压缩
看了一下的访问两比较大,现在js和css的合并压缩整理一下。

首先还是需要一个handler来处理文件的合并、压缩、缓存,.js和css的压缩我们采用的是yahoo.yui.compressor,所以需要引用yahoo.yui.compressor.dll文件

代码如下:


[csharp] view plaincopyprint?public class combinefiles : ihttphandler 
   { 
 
       public void processrequest(httpcontext context) 
       { 
           context.response.contenttype = "text/javascript"; 
           httprequest request = context.request; 
           httpresponse response = context.response; 
           string[] allkeys = request.querystring.allkeys; 
           if (!allkeys.contains("href") || !allkeys.contains("type") || !allkeys.contains("compress")) 
           { 
               response.write("请求格式不正确,正确格式是type=....&href=....&compress=..."); 
               response.write("type只能是js或则css,compress只能是true或则false,href则是请求的文件,多个文件已逗号分隔"); 
           } 
           else 
           { 
               string cachekey = request.url.query; 
               #region /*确定合并文件类型*/  
               string filetype = request.querystring["type"].trim().tolower(); 
               string contentype = string.empty; 
               if (filetype.equals("js")) 
               { 
                   contentype = "text/javascript"; 
               } 
               else if (filetype.equals("css")) 
               { 
                   contentype = "text/css"; 
               } 
               /*确定合并文件类型*/
               #endregion  
               cacheitem cacheitem = httpruntime.cache.get(cachekey) as cacheitem;//服务端缓存  
               if (cacheitem == null) 
               { 
                   #region 合并压缩文件  
                   /*合并文件*/ 
                   string href = context.request.querystring["href"].trim(); 
                   string content = string.empty; 
                   string[] files = href.split(new string[] { ",", "," }, stringsplitoptions.removeemptyentries); 
                   stringbuilder sb = new stringbuilder(); 
                   foreach (string filename in files) 
                   { 
                       string filepath = context.server.mappath(filename); 
                       if (file.exists(filepath)) 
                       { 
                           string readstr = file.readalltext(filepath, encoding.utf8); 
                           sb.append(readstr); 
                           //content = javascriptcompressor.compress(content);  
                           //response.write(content);  
                       } 
                       else 
                       { 
                           sb.appendline("\r\n未找到源文件" + filepath + "\r\n"); 
                       } 
                   } 
                   content = sb.tostring(); 
                   /*合并文件*/ 
                   /*压缩文件*/ 
                   string compressstr = request.querystring["compress"].trim(); 
                   bool iscompress = bool.parse(compressstr); 
                   if (iscompress) 
                   { 
                       if (filetype.equals("js")) 
                       { 
                           content = javascriptcompressor.compress(content); 
                       } 
                       else if (filetype.equals("css")) 
                       { 
                           content = csscompressor.compress(content); 
                       } 
                   } 
                   /*压缩文件*/
                   #endregion  
                   cacheitem = new cacheitem() { content = content, expires = datetime.now.addhours(1) }; 
                   httpruntime.cache.insert(cachekey, cacheitem, null, cacheitem.expires, timespan.zero); 
               } 
               response.contenttype = contentype; 
               if (request.headers["if-modified-since"] != null && timespan.fromticks(cacheitem.expires.ticks - datetime.parse(request.headers["if-modified-since"]).ticks).seconds < 100) 
               { 
                   response.statuscode = 304; 
                   // response.headers.add("content-encoding", "gzip");    
                   response.statusdescription = "not modified"; 
               } 
               else 
               { 
                   response.write(cacheitem.content); 
                   setclientcaching(response, datetime.now); 
               } 
           }  //合并文件结束  
       } 
       private void setclientcaching(httpresponse response, datetime lastmodified) 
       { 
           response.cache.setetag(lastmodified.ticks.tostring()); 
           response.cache.setlastmodified(lastmodified); 
           //public 以指定响应能由客户端和共享(代理)缓存进行缓存。      
           response.cache.setcacheability(httpcacheability.public); 
           //是允许文档在被视为陈旧之前存在的最长绝对时间。      
           response.cache.setmaxage(new timespan(7, 0, 0, 0)); 
           //将缓存过期从绝对时间设置为可调时间      
           response.cache.setslidingexpiration(true); 
       } 
       class cacheitem 
       { 
           public string content { set; get; } 
           public datetime expires { set; get; } 
       } 
       public bool isreusable 
       { 
           get 
           { 
               return false; 
           } 
       } 
   } 

 public class combinefiles : ihttphandler
    {

        public void processrequest(httpcontext context)
        {
            context.response.contenttype = "text/javascript";
            httprequest request = context.request;
            httpresponse response = context.response;
            string[] allkeys = request.querystring.allkeys;
            if (!allkeys.contains("href") || !allkeys.contains("type") || !allkeys.contains("compress"))
            {
                response.write("请求格式不正确,正确格式是type=....&href=....&compress=...");
                response.write("type只能是js或则css,compress只能是true或则false,href则是请求的文件,多个文件已逗号分隔");
            }
            else
            {
                string cachekey = request.url.query;
                #region /*确定合并文件类型*/
                string filetype = request.querystring["type"].trim().tolower();
                string contentype = string.empty;
                if (filetype.equals("js"))
                {
                    contentype = "text/javascript";
                }
                else if (filetype.equals("css"))
                {
                    contentype = "text/css";
                }
                /*确定合并文件类型*/
                #endregion
                cacheitem cacheitem = httpruntime.cache.get(cachekey) as cacheitem;//服务端缓存
                if (cacheitem == null)
                {
                    #region 合并压缩文件
                    /*合并文件*/
                    string href = context.request.querystring["href"].trim();
                    string content = string.empty;
                    string[] files = href.split(new string[] { ",", "," }, stringsplitoptions.removeemptyentries);
                    stringbuilder sb = new stringbuilder();
                    foreach (string filename in files)
                    {
                        string filepath = context.server.mappath(filename);
                        if (file.exists(filepath))
                        {
                            string readstr = file.readalltext(filepath, encoding.utf8);
                            sb.append(readstr);
                            //content = javascriptcompressor.compress(content);
                            //response.write(content);
                        }
                        else
                        {
                            sb.appendline("\r\n未找到源文件" + filepath + "\r\n");
                        }
                    }
                    content = sb.tostring();
                    /*合并文件*/
                    /*压缩文件*/
                    string compressstr = request.querystring["compress"].trim();
                    bool iscompress = bool.parse(compressstr);
                    if (iscompress)
                    {
                        if (filetype.equals("js"))
                        {
                            content = javascriptcompressor.compress(content);
                        }
                        else if (filetype.equals("css"))
                        {
                            content = csscompressor.compress(content);
                        }
                    }
                    /*压缩文件*/
                    #endregion
                    cacheitem = new cacheitem() { content = content, expires = datetime.now.addhours(1) };
                    httpruntime.cache.insert(cachekey, cacheitem, null, cacheitem.expires, timespan.zero);
                }
                response.contenttype = contentype;
                if (request.headers["if-modified-since"] != null && timespan.fromticks(cacheitem.expires.ticks - datetime.parse(request.headers["if-modified-since"]).ticks).seconds < 100)
                {
                    response.statuscode = 304;
                    // response.headers.add("content-encoding", "gzip"); 
                    response.statusdescription = "not modified";
                }
                else
                {
                    response.write(cacheitem.content);
                    setclientcaching(response, datetime.now);
                }
            }  //合并文件结束
        }
        private void setclientcaching(httpresponse response, datetime lastmodified)
        {
            response.cache.setetag(lastmodified.ticks.tostring());
            response.cache.setlastmodified(lastmodified);
            //public 以指定响应能由客户端和共享(代理)缓存进行缓存。   
            response.cache.setcacheability(httpcacheability.public);
            //是允许文档在被视为陈旧之前存在的最长绝对时间。   
            response.cache.setmaxage(new timespan(7, 0, 0, 0));
            //将缓存过期从绝对时间设置为可调时间   
            response.cache.setslidingexpiration(true);
        }
        class cacheitem
        {
            public string content { set; get; }
            public datetime expires { set; get; }
        }
        public bool isreusable
        {
            get
            {
                return false;
            }
        }
    }
同样我们还需要写一个扩展方法:


[csharp] view plaincopyprint?namespace system.web.mvc.html 

    using system; 
    using system.collections.generic; 
    using system.linq; 
    using system.web; 
    using system.web.mvc; 
    using system.text; 
    using system.collections; 
 
    public static class combinejscss 
    { 
        class appendinfo 
        { 
            public string url { set; get; } 
            public int group { set; get; } 
            public int order { set; get; } 
        } 
        const string jsappendfilekey = "jsappendfilekey"; 
        const string jsremovefilekey = "jsremovefilekey"; 
        const string jsremovegroupkey = "jsremovegroupkey"; 
        const string cssappendfilekey = "cssappendfilekey"; 
        const string cssremovefilekey = "cssremovefilekey"; 
        const string cssremovegroupkey = "cssremovegroupkey"; 
 
        #region private method  
 
        private static void appendfiles(htmlhelper htmlhelper, string url, int group, int order, string appendfilekey) 
        { 
            dictionary<string, appendinfo> files = null; 
            url = url.tolower().trim(); 
            if (string.isnullorempty(url)) return; 
            idictionary items = htmlhelper.viewcontext.httpcontext.items; 
            if (items.contains(appendfilekey)) 
            { 
                files = items[appendfilekey] as dictionary<string, appendinfo>; 
            } 
            else 
            { 
                files = new dictionary<string, appendinfo>(); 
                items.add(appendfilekey, files); 
            } 
            if (files.keys.contains(url)) 
            { 
                files[url].group = group; 
                files[url].order = order; 
            } 
            else 
            { 
                files.add(url, new appendinfo() { url = url, group = group, order = order }); 
            } 
 
            items[appendfilekey] = files; 
        } 
 
        private static void removefiles(htmlhelper htmlhelper, string url, int? group, string removefilekey, string removegroupkey) 
        { 
            
            idictionary items = htmlhelper.viewcontext.httpcontext.items; 
            if (!string.isnullorempty(url)) 
            { 
                url = url.trim().tolower(); 
                list<string> removefilekeys = null; 
                if (items.contains(removefilekey)) 
                { 
                    removefilekeys = items[removefilekey] as list<string>; 
                } 
                else 
                { 
                    removefilekeys = new list<string>(); 
                    items.add(removefilekey, removefilekeys); 
                } 
                if (!removefilekeys.contains(url)) 
                { 
 
                    removefilekeys.add(url); 
                } 
                /*按照js的地址移除*/ 
            } 
            if (group.hasvalue) 
            { 
                list<int> removegroupkeys = null; 
                if (items.contains(removegroupkey)) 
                { 
                    removegroupkeys = items[removegroupkey] as list<int>; 
                } 
                else 
                { 
                    removegroupkeys = new list<int>(); 
                    items.add(removegroupkey, removegroupkeys); 
                } 
                if (!removegroupkeys.contains(group.value)) 
                { 
                    removegroupkeys.add(group.value); 
                } 
                /*按照js的group移除*/ 
            } 
        } 
 
        private static mvchtmlstring renderfiles(htmlhelper htmlhelper, string appendfilekey, string removefilekey, string removegroupkey, func<string, string> fun) 
        { 
            dictionary<string, appendinfo> appendfiles = null; 
            stringbuilder content = new stringbuilder(); 
            idictionary items = htmlhelper.viewcontext.httpcontext.items; 
            if (items.contains(appendfilekey)) 
            { 
                appendfiles = items[appendfilekey] as dictionary<string, appendinfo>; 
                list<string> removefilekeys = new list<string>(); 
                if (items.contains(removefilekey)) 
                { 
                    removefilekeys = items[removefilekey] as list<string>; 
                } 
                list<int> removegroupkeys = new list<int>(); 
                if (items.contains(removegroupkey)) 
                { 
                    removegroupkeys = items[removegroupkey] as list<int>; 
                } 
                list<appendinfo> files = appendfiles.select(x => x.value) 
                    .where(x => !removefilekeys.contains(x.url) && !removegroupkeys.contains(x.group)) 
                    .tolist<appendinfo>(); 
 
                ienumerable<igrouping<int, appendinfo>> groupfiles = files.orderby(x => x.group).groupby(x => x.group); 
                foreach (igrouping<int, appendinfo> item in groupfiles) 
                { 
                    string filepath = item.orderby(x => x.order).select(x => x.url).toarray().aggregate((x, y) => x + "," + y); 
                    content.append(fun(filepath)); 
                } 
 
 
            }//end if  
            return new mvchtmlstring(content.tostring()); 
        } 
        #endregion 
 
        #region public method  
        public static void appendjsfille(this htmlhelper htmlhelper, string url, int group = 1, int order = 1) 
        { 
            appendfiles(htmlhelper, url, group, order, jsappendfilekey); 
        } 
 
        public static void removejsfille(this htmlhelper htmlhelper, string url, int? group=null) 
        { 
            removefiles(htmlhelper, url, group, jsremovefilekey, jsremovegroupkey); 
        } 
 
        public static mvchtmlstring renderjsfille(this htmlhelper htmlhelper) 
        { 
            return renderfiles(htmlhelper, jsappendfilekey, jsremovefilekey, jsremovegroupkey, x => 
            { 
                string jsformat = "<script type=\"text/javascript\" src=\"/combinefiles.ashx?type=js&compress=true&href={0}\"></script>"; 
                return string.format(jsformat, x); 
            }); 
        } 
 
        public static void appendcssfille(this htmlhelper htmlhelper, string url, int group = 1, int order = 1) 
        { 
            appendfiles(htmlhelper, url, group, order, cssappendfilekey); 
        } 
 
        public static void removecssfille(this htmlhelper htmlhelper, string url, int? group=null) 
        { 
            removefiles(htmlhelper, url, group, cssremovefilekey, cssremovegroupkey); 
        } 
 
        public static mvchtmlstring rendercssfille(this htmlhelper htmlhelper) 
        { 
            return renderfiles(htmlhelper, cssappendfilekey, cssremovefilekey, cssremovegroupkey, x => 
            { 
                string cssformat = "<link charset=\"utf-8\" rel=\"stylesheet\" type=\"text/css\" href=\"/combinefiles.ashx?type=js&compress=false&href={0}\">"; 
                return string.format(cssformat, x); 
            }); 
        } 
        #endregion  
 
    } 

namespace system.web.mvc.html
{
    using system;
    using system.collections.generic;
    using system.linq;
    using system.web;
    using system.web.mvc;
    using system.text;
    using system.collections;

    public static class combinejscss
    {
        class appendinfo
        {
            public string url { set; get; }
            public int group { set; get; }
            public int order { set; get; }
        }
        const string jsappendfilekey = "jsappendfilekey";
        const string jsremovefilekey = "jsremovefilekey";
        const string jsremovegroupkey = "jsremovegroupkey";
        const string cssappendfilekey = "cssappendfilekey";
        const string cssremovefilekey = "cssremovefilekey";
        const string cssremovegroupkey = "cssremovegroupkey";

        #region private method

        private static void appendfiles(htmlhelper htmlhelper, string url, int group, int order, string appendfilekey)
        {
            dictionary<string, appendinfo> files = null;
            url = url.tolower().trim();
            if (string.isnullorempty(url)) return;
            idictionary items = htmlhelper.viewcontext.httpcontext.items;
            if (items.contains(appendfilekey))
            {
                files = items[appendfilekey] as dictionary<string, appendinfo>;
            }
            else
            {
                files = new dictionary<string, appendinfo>();
                items.add(appendfilekey, files);
            }
            if (files.keys.contains(url))
            {
                files[url].group = group;
                files[url].order = order;
            }
            else
            {
                files.add(url, new appendinfo() { url = url, group = group, order = order });
            }

            items[appendfilekey] = files;
        }

        private static void removefiles(htmlhelper htmlhelper, string url, int? group, string removefilekey, string removegroupkey)
        {
          
            idictionary items = htmlhelper.viewcontext.httpcontext.items;
            if (!string.isnullorempty(url))
            {
                url = url.trim().tolower();
                list<string> removefilekeys = null;
                if (items.contains(removefilekey))
                {
                    removefilekeys = items[removefilekey] as list<string>;
                }
                else
                {
                    removefilekeys = new list<string>();
                    items.add(removefilekey, removefilekeys);
                }
                if (!removefilekeys.contains(url))
                {

                    removefilekeys.add(url);
                }
                /*按照js的地址移除*/
            }
            if (group.hasvalue)
            {
                list<int> removegroupkeys = null;
                if (items.contains(removegroupkey))
                {
                    removegroupkeys = items[removegroupkey] as list<int>;
                }
                else
                {
                    removegroupkeys = new list<int>();
                    items.add(removegroupkey, removegroupkeys);
                }
                if (!removegroupkeys.contains(group.value))
                {
                    removegroupkeys.add(group.value);
                }
                /*按照js的group移除*/
            }
        }

        private static mvchtmlstring renderfiles(htmlhelper htmlhelper, string appendfilekey, string removefilekey, string removegroupkey, func<string, string> fun)
        {
            dictionary<string, appendinfo> appendfiles = null;
            stringbuilder content = new stringbuilder();
            idictionary items = htmlhelper.viewcontext.httpcontext.items;
            if (items.contains(appendfilekey))
            {
                appendfiles = items[appendfilekey] as dictionary<string, appendinfo>;
                list<string> removefilekeys = new list<string>();
                if (items.contains(removefilekey))
                {
                    removefilekeys = items[removefilekey] as list<string>;
                }
                list<int> removegroupkeys = new list<int>();
                if (items.contains(removegroupkey))
                {
                    removegroupkeys = items[removegroupkey] as list<int>;
                }
                list<appendinfo> files = appendfiles.select(x => x.value)
                    .where(x => !removefilekeys.contains(x.url) && !removegroupkeys.contains(x.group))
                    .tolist<appendinfo>();

                ienumerable<igrouping<int, appendinfo>> groupfiles = files.orderby(x => x.group).groupby(x => x.group);
                foreach (igrouping<int, appendinfo> item in groupfiles)
                {
                    string filepath = item.orderby(x => x.order).select(x => x.url).toarray().aggregate((x, y) => x + "," + y);
                    content.append(fun(filepath));
                }


            }//end if
            return new mvchtmlstring(content.tostring());
        }
        #endregion

        #region public method
        public static void appendjsfille(this htmlhelper htmlhelper, string url, int group = 1, int order = 1)
        {
            appendfiles(htmlhelper, url, group, order, jsappendfilekey);
        }

        public static void removejsfille(this htmlhelper htmlhelper, string url, int? group=null)
        {
            removefiles(htmlhelper, url, group, jsremovefilekey, jsremovegroupkey);
        }

        public static mvchtmlstring renderjsfille(this htmlhelper htmlhelper)
        {
            return renderfiles(htmlhelper, jsappendfilekey, jsremovefilekey, jsremovegroupkey, x =>
            {
                string jsformat = "<script type=\"text/javascript\" src=\"/combinefiles.ashx?type=js&compress=true&href={0}\"></script>";
                return string.format(jsformat, x);
            });
        }

        public static void appendcssfille(this htmlhelper htmlhelper, string url, int group = 1, int order = 1)
        {
            appendfiles(htmlhelper, url, group, order, cssappendfilekey);
        }

        public static void removecssfille(this htmlhelper htmlhelper, string url, int? group=null)
        {
            removefiles(htmlhelper, url, group, cssremovefilekey, cssremovegroupkey);
        }

        public static mvchtmlstring rendercssfille(this htmlhelper htmlhelper)
        {
            return renderfiles(htmlhelper, cssappendfilekey, cssremovefilekey, cssremovegroupkey, x =>
            {
                string cssformat = "<link charset=\"utf-8\" rel=\"stylesheet\" type=\"text/css\" href=\"/combinefiles.ashx?type=js&compress=false&href={0}\">";
                return string.format(cssformat, x);
            });
        }
        #endregion

    }
}来看看我们的调用吧,先看看3个view :index.cshtml、demo.cshtml、test.cshtml

 web优化之-Asp.net MVC js、css动态合并 动态压缩
 


那么再来看看_layout.cshtml吧:

 web优化之-Asp.net MVC js、css动态合并 动态压缩

运行的结果如图,请注意js和cs