web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载

摘要:
我们已经有一段时间没有开始网络前端部分了。我想和你分享一些在web上加载js文件的经验。request.QueryString.AllKeys.Contains){response.Write;}否则{stringref=context.Request.QueryString[“href”].Trim();string[]files=href.Split;foreach{stringefilePath=context.Server.MapPath;if{strigcontent=File.ReadAllText;content=JavaScriptCompressor.Compress;response.Write;}否则{response.Write;}}}}publicboolIsReusable{get{returnfalse;}}当我们在浏览器中访问js时,例如:http://localhost:58798/js.ashx?href=scripts/jquery.lazyload.js,scripts/jquery.validate。js返回的结果如图所示:然而,为了追求js的合并和压缩,实际开发中的许多项目都不友好地将js的引用放在一个地方并编写一个长字符串,例如上面的js引用。让我们来谈谈如何改进:publicstaticclassExtensions{conststringjsFileKey=“JSFileKey”;staticstringjshandlerUrl=string.Empty;publicstaticstringJsHandlerUrl{get{if{jshandlerUrl=ConfigurationManager.AppSettings[“jshandlerUrl”]??

做web前段也有一段时间了,对于web中js文件的加载有些体会想跟大家一起分享一下。

1.首先说说js文件的合并和压缩吧

为了便于集中式管理js的合并和压缩我们创建一个Js.ashx文件来专门处理合并压缩,这里我们借用Yahoo.Yui.Compressor工具来压缩我们的js文件

代码如下:

 public classJs : IHttpHandler
    {

        public voidProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/javascript";
            HttpRequest request =context.Request;
            HttpResponse response =context.Response;
            if (!request.QueryString.AllKeys.Contains("href"))
            {
                response.Write("No Content");
            }
            else{
                string href = context.Request.QueryString["href"].Trim();
                string[] files = href.Split(new string[]{",",""},StringSplitOptions.RemoveEmptyEntries);
                foreach (string fileName infiles)
                {
                    string filePath =context.Server.MapPath(fileName);
                    if(File.Exists(filePath))
                    {
                        string content =File.ReadAllText(filePath, Encoding.UTF8);
                        content =JavaScriptCompressor.Compress(content);
                        response.Write(content);
                    }
                    else{
                        response.Write("\r\n未找到源文件"+filePath+"\r\n");
                    }
                }
            }
        }

        public boolIsReusable
        {
            get{
                return false;
            }
        }
    }

当我们在浏览器访问js时如:

http://localhost:58798/js.ashx?href=scripts/jquery.lazyload.js,scripts/jquery.validate.js

返回结果如图:

web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载第1张

但是在实际开发中很多项目为了追求js的合并和压缩,开发很不友好把js的引用放在一个地方,写了很长的一串啊,如上面js引用。

下面说说如何改善吧:

 public static classExtensions
    {
        const string jsFileKey = "JSFileKey";
        static string jshandlerUrl = string.Empty;
        public static stringJsHandlerUrl
        {
            get{
                if (string.IsNullOrEmpty(jshandlerUrl))
                {
                    jshandlerUrl = ConfigurationManager.AppSettings["jsHandlerUrl"] ?? string.Empty;
                }
                returnjshandlerUrl;
            }
        }

        public static void AppendJsFile(this HtmlHelper htmlHelper, string jsFile, int group = 1)
        {
            NameValueCollection jsFiles = null;
            if(htmlHelper.ViewContext.HttpContext.Items.Contains(jsFileKey))
            {
                jsFiles = htmlHelper.ViewContext.HttpContext.Items[jsFileKey] asNameValueCollection;
            }
            else{
                jsFiles = newNameValueCollection();
                htmlHelper.ViewContext.HttpContext.Items.Add(jsFileKey, jsFiles);
            }
            if(jsFiles.AllKeys.Contains(group.ToString()))
            {
                string fileUrl =jsFiles[group.ToString()];
                if (!fileUrl.Contains(jsFile))
                    jsFiles.Add(group.ToString(), jsFile);
            }
            else{
                jsFiles.Add(group.ToString(), jsFile);
            }

            htmlHelper.ViewContext.HttpContext.Items[jsFileKey] =jsFiles;
        }

        public static MvcHtmlString RenderJsFile(thisHtmlHelper htmlHelper)
        {
            NameValueCollection jsFiles = null;
            StringBuilder content = newStringBuilder();
            if(htmlHelper.ViewContext.HttpContext.Items.Contains(jsFileKey))
            {
                jsFiles = htmlHelper.ViewContext.HttpContext.Items[jsFileKey] asNameValueCollection;
                List<string> jsKeys = jsFiles.AllKeys.OrderBy(x => x).ToList<string>();

                string jsFormat = "<script type=\"text/javascript\" src=\"{0}\"></script>";
                foreach (string key injsKeys)
                {
                    string jsFile =jsFiles[key];
                    content.AppendFormat(jsFormat, JsHandlerUrl +jsFile);
                    //htmlHelper.ViewContext.HttpContext.Response.Write(string.Format(jsFormat, JsHandlerUrl + jsFile));
}
            }
            return newMvcHtmlString(content.ToString());
        }
    }

这样在开发的时候我们书写代码就很方便了如:

@{Html.AppendJsFile("Scripts/jquery.lazyload.js");}

这样把所有的js文件缓存起来,最后在调用 @Html.RenderJsFile() 一次性全部输出js。如:

web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载第2张

至于为什么这样写我就不多说了,这种思想在mvc中的RenderPartial和RenderAction都是可用的,如

web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载第3张

重复的js引用也在Js.ashx去掉是不是很方便啊

最后生成的html代码:

web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载第4张

2.下面我们来看看js的延迟加载,为了实现js延迟加载我们需要引用相关的js,在这里我用的是lazyload.js,具体请参考http://blog.csdn.net/dz45693/article/details/7529584

延迟加载后的效果

web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载第5张

在文档加载前只加载了一个2.2k的lazyload.js文件,其他的js文件都在ready后加载。

相应的html代码

web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载第6张

3.下面再来看看js的缓存吧,缓存涉及到要做服务端和客户端缓存,客户端缓存说白了就是做304返回

修改后的代码:

  classCacheItem
        {
            public string Content { set; get; }
            public DateTime Expires { set; get; }
        }
        public voidProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/javascript";
            HttpRequest request =context.Request;
            HttpResponse response =context.Response;
            if (!request.QueryString.AllKeys.Contains("href"))
            {
                response.Write("No Content");
            }
            else{
                string href = context.Request.QueryString["href"].Trim();
                string[] files = href.Split(new string[] { ",", ""}, StringSplitOptions.RemoveEmptyEntries);
                CacheItem item = null;
                object obj = HttpRuntime.Cache.Get(href);//服务端缓存
                if (null ==obj)
                {
                    StringBuilder allText = newStringBuilder();
                    foreach (string fileName infiles)
                    {
                        string filePath =context.Server.MapPath(fileName);
                        if(File.Exists(filePath))
                        {
                            string content =File.ReadAllText(filePath, Encoding.UTF8);
                            content =JavaScriptCompressor.Compress(content);
                            //response.Write(content);
allText.Append(content);
                        }
                        else{
                            //response.Write("\r\n未找到源文件"+filePath+"\r\n");
                            allText.Append("\r\n未找到源文件" + filePath + "\r\n");
                        }
                    }//end foreach
                     item = new CacheItem() { Content = allText.ToString(), Expires = DateTime.Now.AddHours(1) };
                     HttpRuntime.Cache.Insert(href, item, null, item.Expires, TimeSpan.Zero);
                }
                else{
                    item = obj asCacheItem;
                }
                if (request.Headers["If-Modified-Since"] != null && TimeSpan.FromTicks(item.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(item.Content);
                    SetClientCaching(response, DateTime.Now);
                }
            }//end else href
}
        private voidSetClientCaching(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);
        }  

运行效果如图:

web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载第7张

代码下载地址:http://download.csdn.net/detail/dz45693/4272920

免责声明:文章转载自《web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SVM(二)拉格朗日对偶问题ODBC连接EXCEL的一些问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

c++之标准库iomanip

C++ 标准库之iomanip istream & istream::get(char *, int, char = ‘ ’); istream & istream::getline(char *, int, char = ‘ ’); 作用: 从文本中提取指定个数的字符串, 并在串数组末尾添加一个空字符. 区别: get() 不从流中提取终...

boost中的有用工具assign和uuid

assign assign重载‘+’=和‘,’实现连续赋值 assign不仅支持所有8个STL标准容器(vector、string、deque、list、set、multiset、map、multimap)。也对stl中的容器适配器提供了适当的支持,包括queue和priority_queue 演示样例代码: int testAssign() {...

开发规约(一)接口统一返回值格式

一、前言 上篇在介绍 Spring Boot 集成 Dubbo 时,埋下了有关返回值格式的一个小小伏笔。本篇将主要介绍一种常用的返回值格式以及通过什么手段去达成这个目的。 二、Dubbo 接口统一返回值格式 我们在应用中经常会涉及到 server 和 client 的交互,目前比较流行的是基于 json 格式的数据交互。但是 json 只是消息的格式,其...

js实现代彩色文字的下落

<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title>闪烁</title></head><style> *{margin:0}/* 解决兼容性问题   ...

WPF 创建桌面快捷方式

#region 创建桌面快捷方式 string deskTop = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop); string dirPath = System.Environment.CurrentDirectory;...

Winform设置开机启动-操作注册表

#region 设置开机运行 /// <summary> /// 设置开机运行 /// </summary> /// <param name="R_startPath">需要运行的程序.exe</param> /// <returns></returns> public static...