asp.net中js合并,压缩
紧接着上一篇文章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的专栏