asp.net中js合并,压缩

来源:岁月联盟 编辑:exp 时间:2012-05-05

紧接着上一篇文章js文件 合并 压缩 去掉重复引用 缓存 延迟加载http://www.2cto.com/kf/201205/130024.html来说,遗留了一个很大的问题那就是js文本怎么合并与压缩了,上一篇文章中的

[csharp]
public static void AppendJsFile(this HtmlHelper htmlHelper, string jsFile, int group = 1) 
      public static MvcHtmlString RenderJsFile(this HtmlHelper htmlHelper) 
都只限于MVC中使用,我们能不能搞一个更通用的东东了,答案是肯定的。
先说说思路吧,其实很简单 就是我们自己接管输出流,如何接管了?在Global.asax文件中添加以下代码:

[csharp]
public override void Init() 
      { 
          base.Init(); 
          this.ReleaseRequestState += new EventHandler(InstallResponseFilter); 
      } 
      private void InstallResponseFilter(object sender, EventArgs e) 
      { 
          HttpResponse response = HttpContext.Current.Response; 
 
          if (response.ContentType == "text/html") 
              response.Filter = new PageFilter(response.Filter); 
      } 
我还是沿用先前的项目做demo吧

/

和我们平时的开发没有任何区别,但是返回结果却是如下

/
我们看到js文件和js文本都合并 并且也是压缩了的。

关键的一切还是PageFilter的功劳啊

代码如下:

[html]
public class PageFilter : Stream 
   { 
       Stream responseStream; 
       long position; 
       StringBuilder responseHtml; 
 
       public PageFilter(Stream inputStream) 
       { 
           responseStream = inputStream; 
           responseHtml = new StringBuilder(); 
       } 
 
       #region Filter overrides 
       public override bool CanRead 
       { 
           get { return true; } 
       } 
 
       public override bool CanSeek 
       { 
           get { return true; } 
       } 
 
       public override bool CanWrite 
       { 
           get { return true; } 
       } 
 
       public override void Close() 
       { 
           responseStream.Close(); 
       } 
 
       public override void Flush() 
       { 
           responseStream.Flush(); 
       } 
 
       public override long Length 
       { 
           get { return 0; } 
       } 
 
       public override long Position 
       { 
           get { return position; } 
           set { position = value; } 
       } 
 
       public override long Seek(long offset, SeekOrigin origin) 
       { 
           return responseStream.Seek(offset, origin); 
       } 
 
       public override void SetLength(long length) 
       { 
           responseStream.SetLength(length); 
       } 
 
       public override int Read(byte[] buffer, int offset, int count) 
       { 
           return responseStream.Read(buffer, offset, count); 
       } 
       #endregion 
 
       #region Dirty work 
       public override void Write(byte[] buffer, int offset, int count) 
       { 
           HttpResponse response = HttpContext.Current.Response; 
           string charset = response.Charset ?? "utf-8"; 
           string strBuffer = Encoding.GetEncoding(charset).GetString(buffer, offset, count); 
          
 
           int bodyindex = strBuffer.ToLower().LastIndexOf("</body>"); 
             //js文本 
           Regex reg = new Regex("<script[^>]*>(?<content>[^<]*)</script>",RegexOptions.IgnoreCase|RegexOptions.Multiline); 
           //js引用 
           Regex regSrc = new Regex("src=/"?(?<src>[^'/">]*)/"?",RegexOptions.IgnoreCase|RegexOptions.Multiline); 
           StringBuilder jsContent = new StringBuilder(); 
           List<string> jsSrc = new List<string>(); 
 
           MatchCollection mc = reg.Matches(strBuffer); 
 
           if (mc.Count > 0) 
           { 
               #region 找出js部分 
 
               foreach (Match m in mc) 
               { 
                   string str = m.Groups["content"].Value; 
                   if (!string.IsNullOrEmpty(str)) 
                   { 
                       jsContent.AppendLine(str);//找出js文本 
                   } 
                   else 
                   { 
                       //找出js引用 
                       Match mSrc = regSrc.Match(m.Value); 
                       if (mSrc != null && mSrc.Success) 
                       { 
                           string temp = mSrc.Groups["src"].Value; 
                           if (!jsSrc.Contains(temp)) 
                               jsSrc.Add(temp); 
                       } 
                   } 
               } 
               #endregion 
 
               strBuffer = reg.Replace(strBuffer, string.Empty); 
               if (bodyindex < 0) 
               { 
                   //html 文档还没有结束 
                   MergerJs(jsContent, jsSrc); 
               } 
               else 
               { 
                   #region 带结束标签的html 
                   MergerJs(jsContent, jsSrc); 
                   //生成新的js引用 
                   string jsFileFormat = "<script type=/"text/javascript/" src=/"{0}/"></script>"; 
                   string jshref = string.Format(jsFileFormat, "http://localhost:58798/js.ashx?href=" + string.Join(",", jsSrc)); 
                   //生成新的js文本 
                   string jstextFormat = "<script type=/"text/javascript/">{0}</script>"; 
                   //压缩js文本 
                   string jsContentstr = JavaScriptCompressor.Compress(jsContent.ToString()); 
                   string jsText = string.Format(jstextFormat, jsContentstr); 
                   //插入新生成的js 
                   bodyindex = strBuffer.ToLower().LastIndexOf("</body>"); 
                   strBuffer = strBuffer.Insert(bodyindex, jshref + Environment.NewLine + jsText);             
                   #endregion 
               } 
               byte[] data = Encoding.GetEncoding(charset).GetBytes(strBuffer); 
               responseStream.Write(data, 0, data.Length); 
           } 
           else { 
               responseStream.Write(buffer, offset, count); 
           } 
         
 
       } 
       void MergerJs(StringBuilder jsContent, List<string> jsSrc) 
       { 
           string jsTextKey = "jsTextKey"; 
           string jsFileKey = "jsFileKey"; 
           if (!HttpContext.Current.Items.Contains(jsTextKey)) 
               HttpContext.Current.Items.Add(jsTextKey, jsContent); 
           else 
           { 
               StringBuilder jsTexttemp = HttpContext.Current.Items[jsTextKey] as StringBuilder; 
               jsContent.Insert(0, jsTexttemp.ToString()); 
           } 
           if (!HttpContext.Current.Items.Contains(jsFileKey)) 
               HttpContext.Current.Items.Add(jsFileKey, jsSrc); 
           else 
           { 
               List<string> jsfiletemp = HttpContext.Current.Items[jsTextKey] as List<string>; 
               jsSrc.InsertRange(0, jsfiletemp); 
           } 
       } 
       #endregion 
   } 
说了这么多,这里只是提供一个思想,一个js合并的思想,在真实的项目中还有很多细节需要注意啊。

 

摘自 dz45693的专栏