web优化之-asp.net js延迟加载 js动态合并 js动态压缩

紧接着上一篇文章js文件 合并 压缩 去掉重复引用 缓存 延迟加载来说,遗留了一个很大的问题那就是js文本怎么合并与压缩了,上一篇文章中的

 public static void AppendJsFile(this HtmlHelper htmlHelper, string jsFile, int group = 1)
       public static MvcHtmlString RenderJsFile(this HtmlHelper htmlHelper)
都只限于MVC中使用,我们能不能搞一个更通用的东东了,答案是肯定的。

先说说思路吧,其实很简单 就是我们自己接管输出流,如何接管了?在Global.asax文件中添加以下代码:

  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吧

web优化之-asp.net js延迟加载 js动态合并 js动态压缩_第1张图片

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


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

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

代码如下:

    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 finalHtml = Encoding.GetEncoding(charset).GetString(buffer, offset, count);
            Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);

            if (!eof.IsMatch(finalHtml))
            {
                responseHtml.Append(finalHtml);
            }
            else
            {
                responseHtml.Append(finalHtml);
                 finalHtml = responseHtml.ToString();
                //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(finalHtml);

                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

                    finalHtml = reg.Replace(finalHtml, string.Empty);

                    #region 合并js文本和js引用

                    //生成新的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 = jsContent.ToString();
                    if(!string.IsNullOrEmpty(jsContentstr))
                     jsContentstr = JavaScriptCompressor.Compress(jsContent.ToString());
                    string jsText = string.Format(jstextFormat, jsContentstr);
                    //插入新生成的js
                    int bodyindex = finalHtml.ToLower().LastIndexOf("</body>");
                    finalHtml = finalHtml.Insert(bodyindex, jshref + Environment.NewLine + jsText);
                    #endregion
                }
                byte[] data = Encoding.GetEncoding(charset).GetBytes(finalHtml);
                responseStream.Write(data, 0, data.Length);
            }

        }

        #endregion
    }

说了这么多,这里只是提供一个思想,一个js合并的思想,在真实的项目中还有很多细节需要注意啊。

你可能感兴趣的:(Stream,String,asp.net,buffer,regex,byte)