Thứ Ba, 28 tháng 7, 2015

Kỹ thuật nén website MVC , Webform tăng tốc website

1. Nén nội dung HTML là gì 

- Các bạn truy cập website sau : LapTrinhViet
- Xem mã nguồn website ( nhấn phím F12) ta thấy mã html được nén lại ( các khoảng trắng , commenr được xóa bỏ ) như hình sau : 


- Trong các phiên bản IIS6 , IIS 8 , IIS 8 ... có các tính năng Compress nén html rồi mới trả lại cho Browser .Và các trình duyệt hiện đại cũng hỗ trợ nội dung nén 
- Một vấn đề được đặt ra để dùng các tính năng Compress thì cần bật tính năng này trong IIS ( mà không phải nhà cung cấp hosting nào cũng bật tính năng này ) 
- Ngoài ra với các trình duyệt không hỗ trợ nội dung nén thì vẫn sẽ hiển thị nội dung chưa được nén 
- Đồng thời chúng ta không quản lý được mã cũng như nội dung được nén 
- Vì thế chúng ta tìm tới giải pháp là viết 1 đoạn code nhỏ dùng để xóa các commnet , khoảng trẳng ngay trong mã nguồn của chúng ta hơn là sử dụng tính năng nén của IIS 
- Dưới đây chúng tôi hướng dẫn cách xóa khoảng trắng , commnet trong Webform và MVC 

2. Nén nội dung trong ứng dụng MVC 

2.1 Nén toàn bộ website 

- Đây thực chất là thêm 1 tính năng xóa comment , khoảng trắng cho RazorViewEngine 
- Tạo class nén file html như sau : 
Visual C# Code:
  1. using System.IO;
  2. using System.Text;
  3. using System.Text.RegularExpressions;
  4. using System.Web.Mvc;
  5. namespace VinaWebBase.Optimization
  6. {
  7.     // System.Web.WebPages.dll
  8.     public abstract class MinifyZipHtml<TModel> : System.Web.Mvc.WebViewPage<TModel>
  9.     {
  10.         static Regex REGEX_TAGS = new Regex(@">\s+<", RegexOptions.Compiled);
  11.         static Regex REGEX_ALL = new Regex(@"\s+|\t\s+|\n\s+|\r\s+", RegexOptions.Compiled);      
  12.        public override void Write(object value)
  13.         {
  14.             if (value != null)
  15.             {
  16.                 var html = value.ToString();
  17.                 html = REGEX_TAGS.Replace(html, "> <");
  18.                 html = REGEX_ALL.Replace(html, " ");
  19.                 if (typeof(MvcHtmlString) == value.GetType())
  20.                 {
  21.                     value = new MvcHtmlString(html);
  22.                 }
  23.                 else
  24.                     value = html;              
  25.             }
  26.             base.Write(value);
  27.         }
  28.         public override void WriteLiteral(object value)
  29.         {
  30.             if (value != null)
  31.             {
  32.                 var html = value.ToString();
  33.                 html = REGEX_TAGS.Replace(html, "> <");
  34.                 html = REGEX_ALL.Replace(html, " ");
  35.                 if (typeof(MvcHtmlString) == value.GetType())
  36.                 {
  37.                     value = new MvcHtmlString(html);
  38.                 }
  39.                 else
  40.                     value = html;
  41.              
  42.             }
  43.             base.WriteLiteral(value);
  44.         }      
  45.     }
  46. }
Khai báo sử dụng lớp trên để nén các View được trả về trong các resquest 
- Tại file cấu hình web.config của View ( View/web.config)
Ta đổi đoạn mã sau : 

XML Code:
  1. <system.web.webPages.razor>
  2.     <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  3.     <!--<pages pageBaseType="System.Web.Mvc.WebViewPage">
  4.       <namespaces>
  5.         <add namespace="System.Web.Mvc" />
  6.         <add namespace="System.Web.Mvc.Ajax" />
  7.         <add namespace="System.Web.Mvc.Html" />
  8.         <add namespace="System.Web.Optimization"/>
  9.         <add namespace="System.Web.Routing" />
  10.       </namespaces>
  11.     </pages>-->
  12.     <pages pageBaseType="VinaWebBase.Optimization.MinifyZipHtml">
  13.       <namespaces>
  14.         <add namespace="System.Web.Mvc" />
  15.         <add namespace="System.Web.Mvc.Ajax" />
  16.         <add namespace="System.Web.Mvc.Html" />
  17.         <add namespace="System.Web.Optimization"/>
  18.         <add namespace="System.Web.Routing" />
  19.       </namespaces>
  20.     </pages>
  21.   </system.web.webPages.razor>


- Chú ý cần khai báo chính xác cả namespace lớp MinifyZipHtml
- Khi sử dụng tính năng bundled của MVC 4 thì cần tham chiếu tới file css , script ảo như file vật lý thông thường , không dùng được các khái báo : @Styles.Render , @Scripts.Render
- Ta có thể khai báo trực tiếp các file CSS , Script ảo như nhứng file css , script thật như sau : 
<link href="~/Content/css" rel="stylesheet" />
<script src="~/bundles/modernizr"></script>
<script src="~/bundles/jquery"></script>

- Khi chạy ứng dụng các mã html được zip lại như hình sau : 

Download mã nguồn cho MVC chạy Project được kết quả như hình sau : 



Kiểm tra mã nguồn ta được kết quả như hình sau : 



2.2 Tạo Attribute nén nội dung cho Action của Controller bất kỳ 

- Với việc tạo thêm tính năng cho Razor View ở trên thì toàn bộ website sẽ bị nén 
- Ta có thể khai báo tính năng nén cho 1 Action cần thiết nào đó như sau : 
Tạo lớp Attribute : 

Visual C# Code:
  1. using System.IO;
  2. using System.Text;
  3. using System.Text.RegularExpressions;
  4. using System.Web.Mvc;
  5. namespace VinaWebBase.Optimization
  6. {
  7.         //using System.Web.Mvc;
  8.     public class MinifyHtmlFilter : ActionFilterAttribute
  9.     {
  10.         public override void OnActionExecuting(ActionExecutingContext filterContext)
  11.         {
  12.             var response = filterContext.HttpContext.Response;
  13.             response.Filter = new MinifiedStream(response.Filter);
  14.         }
  15.     }
  16.     public class MinifiedStream : MemoryStream
  17.     {
  18.         private readonly Stream _output;
  19.         public MinifiedStream(Stream stream)
  20.         {
  21.             _output = stream;
  22.         }
  23.         private static readonly Regex Whitespace = new Regex(@"(?<=[^])\t{2,}|(?<=[>])\s{2,}(?=[<])|(?<=[>])\s{2,11}(?=[<])|(?=[\n])\s{2,}", RegexOptions.Compiled);
  24.         public override void Write(byte[] buffer, int offset, int count)
  25.         {
  26.             var html = Encoding.UTF8.GetString(buffer);
  27.             html = Whitespace.Replace(html, string.Empty);
  28.             html = html.Trim();
  29.             _output.Write(Encoding.UTF8.GetBytes(html), offset, Encoding.UTF8.GetByteCount(html));
  30.         }
  31.     }
  32. }

Khai báo sử dụng Attribute trong Controller : 
Visual C# Code:
  1.     [VinaWebBase.Optimization.MinifyZipHtmlFilter]
  2.     public class HomeController : Controller
  3.     {
  4.         public ActionResult Index()
  5.         {        
  6.              return View();
  7.         }
  8.     }

- Có thể khai báo sử dụng cho từng Action như sau : 

Visual C# Code:
  1.     public class HomeController : Controller
  2.     {
  3.        [VinaWebBase.Optimization.MinifyZipHtmlFilter]
  4.         public ActionResult Index()
  5.         {        
  6.              return View();
  7.         }
  8.     }


3. Nén nội dung trong WebForm
 

- Đơn giản hơn trong MVC , trong webform các bạn chỉ cần khai báo phương thức sau trong code behind 
// Khai báo phương thức sau trong code behind

Visual C# Code:
  1.         protected override void Render(HtmlTextWriter writer)
  2.         {
  3.            
  4.             if (this.Request.Headers["X-MicrosoftAjax"] != "Delta=true")
  5.             {
  6.                 System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(@"<script[^>]*>[\w|\t|\r|\W]*?</script>");
  7.                 System.Text.StringBuilder sb = new System.Text.StringBuilder();
  8.                 System.IO.StringWriter sw = new System.IO.StringWriter(sb);
  9.                 HtmlTextWriter hw = new HtmlTextWriter(sw);
  10.                 base.Render(hw);
  11.                 string html = sb.ToString();
  12.                 System.Text.RegularExpressions.MatchCollection mymatch = reg.Matches(html);
  13.                 html = reg.Replace(html, string.Empty);
  14.                 reg = new System.Text.RegularExpressions.Regex(@"(?<=[^])\t{2,}|(?<=[>])\s{2,}(?=[<])|(?<=[>])\s{2,11}(?=[<])|(?=[\n])\s{2,}|(?=[\r])\s{2,}");
  15.                 html = reg.Replace(html, string.Empty);
  16.                 reg = new System.Text.RegularExpressions.Regex(@"</body>");
  17.                 string str = string.Empty;
  18.                 foreach (System.Text.RegularExpressions.Match match in mymatch)
  19.                 {
  20.                     str += match.ToString();
  21.                 }
  22.                 html = reg.Replace(html, str + "</body>");
  23.                 writer.Write(html);
  24.             }
  25.             else
  26.                 base.Render(writer);
  27.         }
Chạy ứng dụng webform ta được kết quả tương tự như ví dụ về MVC

Không có nhận xét nào:

Đăng nhận xét