我一直在研究这个。我找到了关于这个主题的几个资源,他们都倾向于使用相同的方法 - 覆盖Page.Render,使用HtmlTextWriter将输出转换为字符串,然后使用一系列编译的正则表达式来删除额外的空格。 Here is an example
嗯,我尝试了它并且它有效...但是......
在Safari 5.0中,这似乎会导致加载图像和“服务器太忙”错误时出现各种性能问题。 IE 7,FireFox 3.6和谷歌Chrome 6.0似乎工作正常,但我没有对服务器进行过多的压力测试。有时在页面生成时似乎存在滞后,但是一旦将html发送到浏览器,页面就会快速显示。
无论如何,当你考虑它时,让.NET构建所有这些选项卡和换行符只是为了使用字符串解析再次将它们全部删除 - 这是剥离它们的最有效方法,这似乎相当愚蠢。覆盖HtmlTextWriter并将其传递到主页面请求中的树更有意义,以避免将它们放入输出中 - 逻辑上应该有性能增益而不是那种情况下的命中。
即使我只能使用这种方法删除50%的空白,它仍然会使正则表达式的工作少得多 - 这意味着它应该比单独使用正则表达式更好。
我尝试使用控制适配器并覆盖了几个成员
我还尝试重写RenderChildren,Render,BeginRender和EndRender以传递我的自定义HtmlTextWriter,但我似乎无法使一个简单的标签控件在其标记之前删除标签。我还使用Reflector挖掘了框架,但我根本无法弄清楚这些字符是如何生成的 - 我以为我使用的是“全部捕获”方法,但显然我错过了一些东西。
无论如何,这是我想出的。此代码无法按照我希望的方式运行。当然,我也尝试直接覆盖页面上的各种Render方法并传入我的自定义HtmlTextWriter的实例,但这也不起作用。
Public Class PageCompressorControlAdapter
Inherits System.Web.UI.Adapters.ControlAdapter
Protected Overrides Sub RenderChildren(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.RenderChildren(New CompressedHtmlTextWriter(writer))
End Sub
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.Render(New CompressedHtmlTextWriter(writer))
End Sub
Protected Overrides Sub BeginRender(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.BeginRender(New CompressedHtmlTextWriter(writer))
End Sub
Protected Overrides Sub EndRender(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.EndRender(New CompressedHtmlTextWriter(writer))
End Sub
End Class
Public Class CompressedHtmlTextWriter
Inherits HtmlTextWriter
Sub New(ByVal writer As HtmlTextWriter)
MyBase.New(writer, "")
Me.InnerWriter = writer.InnerWriter
Me.NewLine = ""
End Sub
Sub New(ByVal writer As System.IO.TextWriter)
MyBase.New(writer, "")
MyBase.InnerWriter = writer
Me.NewLine = ""
End Sub
Protected Overrides Sub OutputTabs()
'Skip over the tabs
End Sub
Public Overrides Property NewLine() As String
Get
Return ""
End Get
Set(ByVal value As String)
MyBase.NewLine = value
End Set
End Property
Public Overrides Sub WriteLine()
End Sub
Public Overrides Sub WriteLine(ByVal value As Boolean)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Char)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal buffer() As Char)
MyBase.Write(buffer)
End Sub
Public Overrides Sub WriteLine(ByVal buffer() As Char, ByVal index As Integer, ByVal count As Integer)
MyBase.Write(buffer, index, count)
End Sub
Public Overrides Sub WriteLine(ByVal value As Decimal)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Double)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Integer)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Long)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Object)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As Single)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal s As String)
MyBase.Write(s)
End Sub
Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object)
MyBase.Write(format, arg0)
End Sub
Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object, ByVal arg1 As Object)
MyBase.Write(format, arg0, arg1)
End Sub
Public Overrides Sub WriteLine(ByVal format As String, ByVal arg0 As Object, ByVal arg1 As Object, ByVal arg2 As Object)
MyBase.Write(format, arg0, arg1, arg2)
End Sub
Public Overrides Sub WriteLine(ByVal format As String, ByVal ParamArray arg() As Object)
MyBase.Write(format, arg)
End Sub
Public Overrides Sub WriteLine(ByVal value As UInteger)
MyBase.Write(value)
End Sub
Public Overrides Sub WriteLine(ByVal value As ULong)
MyBase.Write(value)
End Sub
End Class
如果您不熟悉控件适配器,只需将下面的xml放在ASP.NET App_Browsers文件夹中的.browser文件中即可。您可以更改controlType以将控件适配器应用于Label或其他内容以用于较小的测试范围。如果我可以使用它,那么在我的项目中添加所有控件并不是一件大事,如果有必要的话。
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.Page"
adapterType="PageCompressorControlAdapter"/>
</controlAdapters>
</browser>
</browsers>
无论如何,你会认为只有一个简单的配置设置,如VerboseHtml =“false”或PreserveHtmlFormatting =“false”或类似的东西。如果你看看MSN.com的输出,他们正在使用某种类似于此的压缩...而且它似乎非常高效。
答案 0 :(得分:1)
解决方案涉及使用我在此处找到的压缩模块的修改版本:
http://omari-o.blogspot.com/2009/09/aspnet-white-space-cleaning-with-no.html
此解决方案实现了一个自定义PageParserFilter,然后在web.config文件中进行配置。这个解决方案的优点在于它在编译时过滤了空白区域,因此在运行时没有性能损失。
然后感谢Aristos和diamandiev,我寻找一种合理的方法来为支持它的浏览器添加压缩到响应流。我找到了另一个可用于此的开源模块:http://blowery.org/httpcompress/
两种方法相结合,性能提升显着 - 远远超过使用其中一种方法。当从页面中删除选项卡时,浏览器似乎渲染得更快。
对于静态内容,我打算使用本文中的方法来压缩这些文件(当然,图像已被压缩):http://www.lostechies.com/blogs/dahlbyk/archive/2010/01/08/script-to-enable-http-compression-gzip-deflate-in-iis-6.aspx
最终解决方案
我已将最终解决方案添加到this Gist。