11

Tôi đang sử dụng System.Web.Optimization mới và đã tạo ra một bó như thế này:bó system.web.optimization GZip

bundles.Add(New ScriptBundle("~/bundles/BaseJS").Include(
       "~/Resources/Core/Javascripts/jquery-1.7.1.js", 
       "~/Resources/Core/Javascripts/jquery-ui-1.8.16.js", 
       "~/Resources/Core/Javascripts/jquery.validate.js", 
       "~/Resources/Core/Javascripts/jquery.validate.unobtrusive.js", 
       "~/Resources/Core/Javascripts/jquery.unobtrusive-ajax.js")) 

và theo quan điểm của tôi, tôi đã thêm này

@System.Web.Optimization.Scripts.Render("~/bundles/BaseJS") 

Trong quá trình sử dụng, URL xuất hiện với tiêu đề hết hạn là 1 năm trong tương lai và loại nội dung của văn bản/javascript

Trong web.config tôi có một số mã cho gzip đang hoạt động trên các tệp JS tĩnh nhưng nó không ' t dường như trên các gói được rút gọn.

<staticContent> 
    <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00"/> 
    <remove fileExtension=".js"/> 
    <mimeMap fileExtension=".js" mimeType="text/javascript"/> 
</staticContent> 
<urlCompression doDynamicCompression="true" doStaticCompression="true" dynamicCompressionBeforeCache="true"/> 
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files"> 
    <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/> 
    <dynamicTypes> 
    <add mimeType="text/*" enabled="true"/> 
    <add mimeType="text/javascript" enabled="true"/> 
    </dynamicTypes> 
    <staticTypes> 
    <add mimeType="text/*" enabled="true"/> 
    <add mimeType="text/javascript" enabled="true"/> 
    </staticTypes> 
</httpCompression> 

Có cách nào để làm cho gói kết xuất gzip nội dung không?

+0

Tôi nghĩ rằng đây có thể là có thể với một iBundleTransform nhưng tôi không chắc chắn như thế nào. https://twitter.com/ericdc1/status/219850852364599298 – ericdc

Trả lời

12

Như bạn đã lưu ý, việc tạo chuyển đổi gói tùy chỉnh bằng cách tạo một lớp triển khai IBundleTransform là đúng cách để đi. Ví dụ, sau đây là một bó dụ chuyển đổi sử dụng các SharpZipLib (via NuGet) để làm Gzip nén:

public class GZipTransform : IBundleTransform 
{ 
    string _contentType; 

    public GZipTransform(string contentType) 
    { 
     _contentType = contentType; 
    } 

    public void Process(BundleContext context, BundleResponse response) 
    { 
     var contentBytes = new UTF8Encoding().GetBytes(response.Content); 

     var outputStream = new MemoryStream(); 
     var gzipOutputStream = new GZipOutputStream(outputStream); 
     gzipOutputStream.Write(contentBytes, 0, contentBytes.Length); 

     var outputBytes = outputStream.GetBuffer(); 
     response.Content = Convert.ToBase64String(outputBytes); 


     // NOTE: this part is broken 
     context.HttpContext.Response.Headers["Content-Encoding"] = "gzip"; 
     response.ContentType = _contentType ; 
    } 
} 

Bây giờ, đây là một phần không may mắn - trong thử nghiệm mẫu này, tôi phát hiện ra một lỗi mà sẽ giữ cho nó khỏi đang làm việc. Thiết kế ban đầu dự kiến ​​rằng mọi người sẽ làm những việc khá đơn giản - và như vậy, BundleResponse cho thấy các thuộc tính cho phép bạn thiết lập nội dung (cụ thể hơn, nội dung chuỗi) và kiểu nội dung. BundleContext cho thấy một thuộc tính của HttpContext, dẫn đến một người hợp lý để tin rằng các thuộc tính bổ sung của một đáp ứng có thể được đặt ở đó (như được hiển thị ở trên). Tuy nhiên, điều này được gây hiểu lầm cho 2 lý do:

  1. biến đổi Bundle đang chạy như một phần của việc tạo ra các bó - và tạo ra những bó xảy ra lần đầu tiên nó được tham chiếu (không dereferenced, như trong, trình duyệt theo Thuộc tính src trong một thẻ script - nhưng được tham chiếu, như trong, khung nhìn gọi phương thức trình trợ giúp Scripts.Render). Trong ví dụ trên, điều này có nghĩa là tiêu đề mã hóa nội dung có giá trị gzip sẽ được đặt trên trang đầu tiên với chế độ xem sử dụng các phương thức trợ giúp của nhóm để tạo liên kết - và nếu nội dung HTTP thực sự không được gzipped, bạn ' sẽ gặp lỗi vì trình duyệt không thể giải mã nội dung HTTP.

  2. Ngay cả khi # 1 không phải là vấn đề, gói được đặt ngay vào bộ nhớ cache ASP.NET sau khi được tạo - vì vậy đường dẫn mã này sẽ chỉ được thực hiện một lần.

Chúng tôi đang tham gia một cái nhìn nghiêm khắc các thiết kế trong phiên bản tiếp theo của khuôn khổ để cho phép bạn chỉ định tất cả (lý tưởng) các khía cạnh của thông điệp HTTP response đó là miễn phí của bối cảnh HTTP (có nghĩa là nó dễ dàng cachable).

Một lưu ý bổ sung. Để cung cấp các biến đổi gói tùy chỉnh, bạn sẽ cần phải quay lại để tạo một phiên bản của Gói thay vì ScriptBundle/StyleBundle. Các lớp đó thực sự chỉ là các loại viết tắt cho các bó với các biến đổi gói được định cấu hình trước.Để tạo một bó dựa trên Bundle, bạn sẽ làm điều gì đó như sau:

var jqueryBundle = new Bundle("~/bundles/jqueryall", new GZipTransform("text/javascript")); 
jqueryBundle.Include("~/Scripts/jquery-1.*", 
    "~/Scripts/jquery-ui*", 
    "~/Scripts/jquery.unobtrusive*", 
    "~/Scripts/jquery.validate*"); 
bundles.Add(jqueryBundle); 
+4

Nó chỉ ra rằng IIS Dynamic Content Compression thực hiện điều này mà không cần tất cả các buổi lễ. Trong trường hợp của tôi, tôi đã phải IISReset sau khi cài đặt DCC để làm cho nó hoạt động vì vậy tôi đã bị lừa khi nghĩ rằng system.web.optimization cần can thiệp vào gzip nhưng nó không. – ericdc

+0

Bạn viết "Chúng tôi đang xem xét kỹ về thiết kế trong phiên bản tiếp theo của khung công tác ...", vì vậy tôi cho rằng bạn là thành viên của nhóm ASP.NET. Bạn có dự định cho phép nội dung byte trong phiên bản tiếp theo không? Điều này sẽ cực kỳ hữu ích cho việc ghép ảnh (sprites). – JohannesH

+2

Điều này có bao giờ được sửa trong System.Web.Optimizations không? Tôi đang ở trong một môi trường mà tôi không thể sử dụng IIS Compression vì vậy điều này có vẻ giống như cách duy nhất khả thi khác hơn là sử dụng một HttpModule. – kkara

5

Nó có thể đạt được bằng HttpModule

public class GzipModule : IHttpModule 
{ 
    #region IHttpModule Members 

    public void Init(HttpApplication application) 
    { 
     application.BeginRequest += Application_BeginRequest; 
    } 

    public void Dispose() 
    { 
    } 

    #endregion 

    private void Application_BeginRequest(Object source, EventArgs e) 
    { 
     HttpContext context = HttpContext.Current; 
     HttpRequest request = context.Request; 
     HttpResponse response = context.Response; 
     string acceptEncoding = request.Headers["Accept-Encoding"]; 

     if (String.IsNullOrEmpty(acceptEncoding)) 
      return; 

     acceptEncoding = acceptEncoding.ToUpperInvariant(); 

     if (acceptEncoding.Contains("GZIP")) 
     { 
      response.AppendHeader("Content-Encoding", "gzip"); 
      response.Filter = new GZipStream(response.Filter, CompressionMode.Compress); 
     } 
     else if (acceptEncoding.Contains("DEFLATE")) 
     { 
      response.AppendHeader("Content-Encoding", "deflate"); 
      response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress); 
     } 
    } 
} 

và đăng ký nó trong cấu hình

<system.webServer> 
    <modules> 
     <add name="Gzip" type="Gecko.Web.GzipModule" /> 
    </modules> 
+2

Đúng, nhưng điều này bây giờ sẽ chạy cho TẤT CẢ các yêu cầu, không chỉ đơn giản cho các gói. –

11

Với sự mới nhất ASP.NET Optimization (v1.1.2), lớp GZipTransform không hoạt động tốt.

Tôi tìm thấy một con đường mới với một Bundle lớp tùy chỉnh mà sẽ luôn luôn nén gói nội dung (đã được chuyển đổi và cached) trước khi trả lời:

public class GZipBundle : Bundle 
{ 
    public GZipBundle(string virtualPath, params IBundleTransform[] transforms) 
     : base(virtualPath, null, transforms) { } 

    public override BundleResponse CacheLookup(BundleContext context) 
    { 
     if (null != context) GZipEncodePage(context.HttpContext); 
     return base.CacheLookup(context); 
    } 

    // Sets up the current page or handler to use GZip through a Response.Filter. 
    public static void GZipEncodePage(HttpContextBase httpContext) 
    { 
     if (null != httpContext && null != httpContext.Request && null != httpContext.Response 
      && (null == httpContext.Response.Filter 
      || !(httpContext.Response.Filter is GZipStream || httpContext.Response.Filter is DeflateStream))) 
     { 
      // Is GZip supported? 
      string acceptEncoding = httpContext.Request.Headers["Accept-Encoding"]; 
      if (null != acceptEncoding 
       && acceptEncoding.IndexOf(DecompressionMethods.GZip.ToString(), StringComparison.OrdinalIgnoreCase) >= 0) 
      { 
       httpContext.Response.Filter = new GZipStream(httpContext.Response.Filter, CompressionMode.Compress); 
       httpContext.Response.AddHeader("Content-Encoding", DecompressionMethods.GZip.ToString().ToLowerInvariant()); 
      } 
      else if (null != acceptEncoding 
       && acceptEncoding.IndexOf(DecompressionMethods.Deflate.ToString(), StringComparison.OrdinalIgnoreCase) >= 0) 
      { 
       httpContext.Response.Filter = new DeflateStream(httpContext.Response.Filter, CompressionMode.Compress); 
       httpContext.Response.AddHeader("Content-Encoding", DecompressionMethods.Deflate.ToString().ToLowerInvariant()); 
      } 

      // Allow proxy servers to cache encoded and unencoded versions separately 
      httpContext.Response.AppendHeader("Vary", "Content-Encoding"); 
     } 
    } 
} 

// Represents a bundle that does CSS minification and GZip compression. 
public sealed class GZipStyleBundle : GZipBundle 
{ 
    public GZipStyleBundle(string virtualPath, params IBundleTransform[] transforms) : base(virtualPath, transforms) { } 
} 

// Represents a bundle that does JS minification and GZip compression. 
public sealed class GZipScriptBundle : GZipBundle 
{ 
    public GZipScriptBundle(string virtualPath, params IBundleTransform[] transforms) 
     : base(virtualPath, transforms) 
    { 
     base.ConcatenationToken = ";" + Environment.NewLine; 
    } 
} 

Sau đó, bạn có thể sử dụng GZipStyleBundleGZipScriptBundle để thay thế Bundle lớp gốc : StyleBundle, ScriptBundle. Ví dụ:

public static class BundleConfig 
{ 
    // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725 
    public static void RegisterBundles(BundleCollection bundles) 
    { 
     bundles.Add(new GZipScriptBundle("~/bundles/jquery.js").Include(...)); 
     bundles.Add(new GZipScriptBundle("~/bundles/jquery-ui.js", new JsMinify()).Include(...)); 

     bundles.Add(new GZipStyleBundle("~/bundles/all.css", new CssMinify()).Include(...)); 
    } 
} 

Trân