これは古い質問ですが、他の誰かに利益をもたらす場合に備えて、ソリューションを投入します。
ほとんどの部分で機能する正規表現を使用した「縮小」フィルターがありました。pre
とタグの空白を保持することになると失敗しましたtextarea
。数日前に壁にぶつかってしまったので、3日ほどかけて他の人が試したことを読んだり、自分のアイデアを試したりしました。最終的に、HtmlAgilityPackを使用してHTMLを解析し、そこから空白ノードを削除することにしました。pre
と要素の空白textarea
はHAPによって空白とは見なされなかったので、それは私の好意でうまくいき、私が望んでいたことを正確に実行しました。HTMLがチャンクで送信されていたため、最初は問題がありましたが、完了するまでバッファリングすることで解決しました。これが他の誰かにとって有益な場合の私のコードです。
このフィルターは、私のアプリケーション(ASP.NET MVC 5)で機能することに注意してください。理想的には、このようなフィルターの必要性を回避するために、公開中にミニファイを実行する必要があります。最後に、彼の回答の@naivistsは、応答を圧縮するGZIPは縮小化よりも優れた効果があると述べていますが、私は彼に少し同意しません。はい、そうなりますが、縮小化により、その上に応答がわずかに減少します。それが本当に輝いているのは、CSSでスタイリングするときです。これは、空白のぶつかりや要素の置き忘れを心配する必要がなく、マージン/パディング/ポジショニングのトリックを使用して修正する必要がないためです。
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
internal sealed class MinifyHtmlAttribute :
ActionFilterAttribute {
public override void OnActionExecuted(
ActionExecutedContext filterContext) {
if (filterContext == null
|| filterContext.IsChildAction) {
return;
}
filterContext.HttpContext.Response.Filter = new MinifyHtmlStream(filterContext.HttpContext);
}
}
internal sealed class MinifyHtmlStream :
MemoryStream {
private readonly MemoryStream BufferStream;
private readonly HttpContextBase Context;
private readonly Stream FilterStream;
public MinifyHtmlStream(
HttpContextBase httpContextBase) {
BufferStream = new MemoryStream();
Context = httpContextBase;
FilterStream = httpContextBase.Response.Filter;
}
public override void Flush() {
BufferStream.Seek(0, SeekOrigin.Begin);
if (Context.Response.ContentType != "text/html") {
BufferStream.CopyTo(FilterStream);
return;
}
var document = new HtmlDocument();
document.Load(BufferStream);
var spans = document.DocumentNode.Descendants().Where(
d =>
d.NodeType == HtmlNodeType.Element
&& d.Name == "span").SelectMany(
d => d.ChildNodes.Where(
cn => cn.NodeType == HtmlNodeType.Text)).ToList();
// Some spans have content that needs to be trimmed.
foreach (var span in spans) {
span.InnerHtml = span.InnerHtml.Trim();
}
var nodes = document.DocumentNode.Descendants().Where(
d =>
(d.NodeType == HtmlNodeType.Text
&& d.InnerText.Trim().Length == 0)
|| (d.NodeType == HtmlNodeType.Comment
&& d.InnerText.Trim() != "<!DOCTYPE html>")).Select(
d => d).ToList();
foreach (var node in nodes) {
node.Remove();
}
document.Save(FilterStream);
}
public override void Write(
byte[] buffer,
int offset,
int count) {
BufferStream.Write(buffer, offset, count);
}
}