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动态压缩

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


我们看到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合并的思想,在真实的项目中还有很多细节需要注意啊。

你可能感兴趣的:(asp.net)