Web性能優化已是老生常談的話題了, 不過筆者也一直沒放在心上,主要的緣由仍是項目的用戶量以及頁面中的js,css文件就那幾個,感受沒什麼優化的。人總要進步的嘛,最近在被angularjs吸引着,也用了angularjs開發了一個項目,那感受真的是誰用誰知道。javascript
angularjs的好處我就不在這裏廢話了,有興趣的請自行度娘。背景是這樣的, 在這個使用angularjs開發的項目中,因爲本身的粗心致使頁面打開很慢,傻了吧唧的引用了未壓縮的js文件,將近1M的js啊,我還傻乎乎的建索引,優化sql,然而最終並無什麼卵用,最後仍是在查請求的時候發現angularjs未壓縮的文件原來那麼大,而後就用了min版本的,瞬間問題解決了。話說到此優化應該就結束了吧,但做爲一個有理想,有抱負的程序員咱不能太容易知足,因此決定再進行優化下,數據庫和程序都已經優化了,那後面就只能來減小網絡的請求數來進行優化了。再加上在學習angularjs的過程當中,發現js也能夠像我們的C#同樣進行模塊化開發(請原諒俺對於前端的小白),那進行模塊化的時候就須要將不一樣的模塊放在不一樣的文件中,這樣問題就來了,咱們頁面的請求數會增多,減小頁面請求的方式就是將多個css文件或者js文件進行合併,最簡單的方法就是人工的進行合併再一塊兒。但人工多傻啊,我們但是勵志改變世界的程序員們,咱不能人工,咱必須智能,因此在園子裏逛了下,多少找到了點頭緒,參考了下別人的博客,總結下下面的方法。css
首先先講下思路,添加一個asp.net處理程序,而後在頁面中的script標籤中的src的值設置爲這個asp.net的處理程序的路徑,並加上一個參數(css相似),以下所示:前端
<link href="/Css/CombineFiles.axd?fn=index" rel="stylesheet" />java
在程序中咱們能夠獲取到fn的值,而後根據fn的值在/css/路徑下面找到對應的文件名,如fn的值爲index,那麼就在/css/文件夾下面找到文件名問index.txt的文件,而後打開讀取文件中的內容,以下所示:程序員
第一行表示的是當前請求的css文件,若是是js文件,則第一行爲js。後面的每行則表示的爲文件名。在上圖中的例子中,表示的是,當前請求的是a.css,b.css,c.css合併和的文件。那咱們只須要將三個文件合併後並輸入就好了。下面直接上代碼:angularjs
public class CombineFiles : IHttpHandler { #region IHttpHandler Members /// <summary> /// 緩存key值 /// </summary> private const string CacheKeyFormat = "_CacheKey_{0}_"; public bool IsReusable { get { return true; } } public void ProcessRequest(HttpContext context) { HttpRequest request = context.Request; HttpResponse response = context.Response; string cachekey = string.Empty; bool flag = false;//標誌是不是最新合併的內容 string fn = request.QueryString["fn"]; if (!string.IsNullOrEmpty(fn)) { cachekey = string.Format(CacheKeyFormat, fn); CompressCacheItem cacheItem = HttpRuntime.Cache[cachekey] as CompressCacheItem; if (cacheItem == null) { flag = true; string path = context.Server.MapPath(""); StringBuilder sb = new StringBuilder(); //找到請求的文本文件 var con = File.ReadAllText(string.Format("{0}\\{1}.txt", path, fn)). Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); response.ContentType = con[0] == "css" ? "text/css" : "text/javascript"; for (int i = 1; i < con.Length; i++) { var filename = string.Format("{0}\\{1}.{2}", path, con[i],con[0]); if (File.Exists(filename)) { string readstr = File.ReadAllText(filename, Encoding.UTF8); sb.Append(readstr); } } cacheItem = new CompressCacheItem() { Type = con[0], Content = sb.ToString(), Expires = DateTime.Now.AddDays(30) }; HttpRuntime.Cache.Insert(cachekey, cacheItem, null, cacheItem.Expires, TimeSpan.Zero); } string ifModifiedSince = request.Headers["If-Modified-Since"]; if (!string.IsNullOrEmpty(ifModifiedSince)&&cacheItem.Expires>DateTime.Parse(ifModifiedSince)&&!flag) { response.StatusCode = (int)System.Net.HttpStatusCode.NotModified; response.StatusDescription = "Not Modified"; } else { response.Write(cacheItem.Content); SetClientCaching(response, cacheItem.Expires); } } } private void SetClientCaching(HttpResponse response, DateTime expires) { response.Cache.SetETag(DateTime.Now.Ticks.ToString()); response.Cache.SetLastModified(DateTime.Now); //public 以指定響應能由客戶端和共享(代理)緩存進行緩存。 response.Cache.SetCacheability(HttpCacheability.Public); //是容許文檔在被視爲陳舊以前存在的最長絕對時間。 response.Cache.SetMaxAge(TimeSpan.FromTicks(expires.Ticks)); response.Cache.SetSlidingExpiration(true); } private class CompressCacheItem { /// <summary> /// 類型 js 或 css /// </summary> public string Type { get; set; } // js css /// <summary> /// 內容 /// </summary> public string Content { set; get; } /// <summary> /// 過時時間 /// </summary> public DateTime Expires { set; get; } } #endregion }
此代碼是在園子裏一個園友的博客的基礎上進行改進的。連接找不到了,在這裏就不貼出來了。web
最後呢,須要在配置文件中加入以下配置信息:sql
<configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> <httpHandlers> <add verb="GET" path="*.axd" type="Angular.CombineFiles"/> </httpHandlers> </system.web> </configuration>
上面的代碼中能夠實現功能是,合併js或css,並將其緩存起來,當每次請求時都會判斷當前瀏覽器中是否有緩存,且是否有效,若是有效則直接響應302,告訴瀏覽器本地緩存是可使用的,不須要從服務器端從新下載,介紹了不少流量,而且提升了速度。假如,在項目升級的過程當中,修改了js或者css,想讓瀏覽器強制下載最新的文件時,可將HttpRuntime.Cache中的緩存移除,這樣當從新請求時,會從新合併文件,並響應到客戶端。數據庫
以下所示:瀏覽器
HttpRuntime.Cache.Remove(string.Format("_CacheKey_{0}_","index"));
over
另外,在這裏推廣下我們的微信開發交流羣,這裏是一羣致力於C#微信開發交流的平臺,歡迎各位同行進行交流。也能夠到羣論壇與你們一塊兒交流學習。
微信開發交流的論壇(微兔碼農說)