zoukankan      html  css  js  c++  java
  • Asp.net MVC WEB 优化之 js、css动态合并 动态压缩

    看了一下的访问两比较大,现在js和css的合并压缩整理一下。

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

    代码如下:

    复制代码
     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;
                }
            }
        }
    复制代码


    同样我们还需要写一个扩展方法:

    复制代码
    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

    那么再来看看_Layout.cshtml吧:

    运行的结果如图,请注意js和css各文件的顺序:

    再来确认缓存吧

    本例代码简单,可能还有一些bug。欢迎大家拍砖。

  • 相关阅读:
    2018常用DOM操作总结
    emlog实现全站pjax无刷新加载页面
    深入理解Vuex 框架
    2018前端最火的web UI框架
    小程序快递单号查询
    表单元素系列二
    表单元素系列一
    表单提交
    AJAX 回调函数刷新页面问题
    electron 常用命令
  • 原文地址:https://www.cnblogs.com/haiyabtx/p/2776447.html
Copyright © 2011-2022 走看看