Я изучал этот вопрос некоторое время. Я нашел несколько ресурсов на эту тему, и все они, как правило, используют один и тот же подход - переопределить 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-файл в файл .browser в папке ASP.NET App_Browsers. Вы можете изменить controlType, чтобы применить адаптер управления к метке или что-то еще для меньшего объема теста. Если мне удастся заставить это работать, не составит большого труда добавить сюда все элементы управления в моем проекте, если это будет необходимо.
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.Page"
adapterType="PageCompressorControlAdapter"/>
</controlAdapters>
</browser>
</browsers>
В любом случае, вы могли бы подумать, что будет простой параметр конфигурации, такой как VerboseHtml = "false" или PreserveHtmlFormatting = "false" или что-то в этом роде. Если вы посмотрите на выходные данные MSN.com, они используют какое-то сжатие, подобное этому ... и оно выглядит очень производительным.