私はしばらくこれを研究してきました。この件に関するいくつかのリソースを見つけましたが、それらはすべて同じアプローチを使用する傾向があります-Page.Renderをオーバーライドし、HtmlTextWriterを使用して出力を文字列に変換し、一連のコンパイルされた正規表現を使用して余分な空白を削除します。ここに例があります。
まあ、私はそれを試してみましたが、うまくいきます...しかし....
Safari 5.0 では、これにより、画像の読み込みや「サーバーがビジー状態です」というエラーが発生するなど、あらゆる種類のパフォーマンスの問題が発生するようです。IE 7、FireFox 3.6、および Google Chrome 6.0 は正常に動作しているようですが、サーバーのストレス テストはあまり行っていません。時折、ページの生成に時間がかかるように見えますが、html がブラウザーに送信されると、ページはすばやく表示されます。
とにかく、考えてみると、.NET にこれらすべてのタブと改行を作成させて、文字列解析 (それらを取り除く最も効率の悪い方法) を使用してそれらをすべて再度削除させるのは、かなりばかげているように思えます。HtmlTextWriter をオーバーライドし、それをメイン ページ リクエストのツリーに渡して、出力にまったく含めないようにする方が理にかなっています。論理的には、その場合、ヒットではなくパフォーマンスが向上するはずです。
この方法を使用して空白の 50% しか削除できない場合でも、正規表現が行う作業ははるかに少なくなります。つまり、正規表現のみを使用する場合よりもパフォーマンスが向上するはずです。
コントロールアダプターを使用して、いくつかのメンバーをオーバーライドしてみました
- WriteLine() へのすべての呼び出しを対応する Write() メソッドに転送する
- NewLine プロパティを空の文字列に設定する
- OutputTabs() メソッドをオーバーライドし、単純にコードを削除する
- Indent プロパティをオーバーライドして 0 を返す
また、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 を変更して、コントロール アダプターをラベルまたはその他のテスト範囲に適用することができます。これを機能させることができれば、プロジェクトのすべてのコントロールをここに追加する必要がある場合は、それほど大したことではありません。
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.Page"
adapterType="PageCompressorControlAdapter"/>
</controlAdapters>
</browser>
</browsers>
いずれにせよ、 VerboseHtml="false" や PreserveHtmlFormatting="false" などの単純な構成設定があるだけだと思うでしょう。MSN.com からの出力を見ると、これに似たある種の圧縮が使用されており、非常にパフォーマンスが高いように見えます。