Kleine hack: CSS Combiner / Minifier ASP.NET Control (Nederlands (Dutch))

Kleine hack: CSS Combiner / Minifier ASP.NET Control

Thursday, 25 March 2010

//

5 minute read

LET OP: Als ik zeg hack ik meen het...dit is in NO WOY productie klaar...het is gewoon een monster in dit stadium. Als het ervoor zorgt dat uw hond te exploderen, niet de schuld van mij!

Ik dacht dat ik gooi een werk in uitvoering online voor mensen om een spel te hebben met. Dit is een van mijn kleine huisdier projecten (Ik ben niet toegestaan om code te schrijven op het werk...niet een dev als ik[Ik heb er altijd aan herinnerd!).

Dus, wat doet het?

Nou, een van de belangrijkste prestatie problemen voor de huidige websites is het aantal verzoeken die ze terug te maken naar de server, niet de werkelijke server-kant verwerkingstijd. schreef hierover na het lezen van Steve Sounders uitstekendWebsites met hoge prestaties Het was eerlijk gezegd een verrassing voor mij! Nou ja, hoe dan ook onlangs heb ik gespeeld met een aantal ASP.NET server control die gericht zijn op het optimaliseren van het aantal server calls een ASP.NET app moet veel minder maken. De eerste van deze is de (nog) ongepubliceerde CSS Sprite Control. Hieronder is het begin van de tweede; dit werd geschreven in een paar uur gisteravond als ik kon niet slapen om na te denken over hoe het zou kunnen werken. De code is zeer ruw, maar het demonstreert het concept vrij goed.

In essentie wilde ik de minimale inspanning mogelijk te combineren en comprimeren meerdere <link rel=stylesheet> CSS-bestandsitems samen, minimaliseer ze met behulp van YUI-compressor (voor .NET...on Codeplex) en voer een tijd afhankelijk (in dit geval, Datum aangepast voor het bestand) hash voor de bestandsnaam (in een vaste locatie op het moment, ~/OutputCSS/

Hoe werkt het?

Stel je voor dat je een pagina had met een aantal stylesheet definities als deze:

   1: <link type="text/css" rel="stylesheet" href="../../../build/logger/assets/logger.css"/>
   2: <link type="text/css" rel="stylesheet" href="../../../build/yuitest/assets/testlogger.css"/>        
   3: <style type="text/css">
   4: #container, #container2 {
   5:     width: 400px;
   6: }
   7:  
   8: .yui-carousel-element {
   9:     margin: 0;
  10:     padding: 0;
  11: }
  12:  
  13: .yui-carousel-element li {
  14:     border: none;
  15:     margin: 0;
  16:     padding: 0;
  17:     width: 100px;
  18: }
  19: </style>

Zoals u kunt zien hebben we twee CSS-bestand definities en een style tag. Zou het niet leuk zijn als we konden combineren en minify deze... nou...here...hoe mijn kleine hacky control laat je het doen:

   1: <asp:CSSManager runat="server">
   2:         <link type="text/css" rel="stylesheet" href="~/build/logger/assets/logger.css"/>
   3:         <link type="text/css" rel="stylesheet" href="../../../build/yuitest/assets/testlogger.css"/>        
   4:         <style type="text/css">
   5:         #container, #container2 {
   6:             width: 400px;
   7:         }
   8:  
   9:         .yui-carousel-element {
  10:             margin: 0;
  11:             padding: 0;
  12:         }
  13:  
  14:         .yui-carousel-element li {
  15:             border: none;
  16:             margin: 0;
  17:             padding: 0;
  18:             width: 100px;
  19:         }
  20:         </style>
  21: </asp:CSSManager>

Je kunt zien in het knipsel hierboven dat we net verpakt de CSS definities in <asp:CSSManager>…</asp:CSSManager> tags...dat is alles wat er is om het! Een ander ding, de oplettende zal hebben gemerkt dat ik nu een ~/ in de href...it.it een mooi neveneffect van deze methode kan gebruiken...laat je het gekke pad doorkruisen spul (../././../)

Uiteraard is dit nog steeds een beetje beperkt, het werkt niet in Partial Trust, niet omgaan met meerdere scopes; zeg, Site level CSS, Page Level CSS en Masterpages waar u meerdere sheets met verschillende inhoud wilt. Plan is om te blijven werken aan dit voor een tijdje ... dus ik zal bijna zeker update dit binnenkort.

Bron volgt

   1: using System;
   2: using System.Collections.Generic;
   3: using System.ComponentModel;
   4: using System.Text;
   5: using System.Web.UI;
   6: using System.Web.UI.HtmlControls;
   7: using System.IO;
   8: using System.Security.Cryptography;
   9: using Yahoo.Yui.Compressor;
  10:  
  11: namespace CSSManager
  12: {
  13:     [DefaultProperty("Text")]
  14:     [ToolboxData("<{0}:CSSManager runat=server></{0}:CSSManager>")]
  15:  
  16:     [ParseChildren(true, "cssFiles")]
  17:     public class CSSManager : Control, INamingContainer
  18:     {
  19:  
  20:         public const string FILE_PATH = "~/OutputCSS/{0}.css";
  21:  
  22:         public CSSManager() { }
  23:  
  24:         public List<HtmlGenericControl> CSSFiles
  25:         {
  26:             get;
  27:             set;
  28:         }
  29:  
  30:  
  31:         private StringBuilder combinedSheets = new StringBuilder();
  32:  
  33:         public string GetStyleSheet(string virtualPath)
  34:         {
  35:             string filePath = Context.Server.MapPath(virtualPath);
  36:             if (!string.IsNullOrEmpty(filePath))
  37:             {
  38:                 return File.ReadAllText(filePath);
  39:             }
  40:             return string.Empty;
  41:  
  42:         }
  43:  
  44:         public string CalculateFileHash(string filePaths)
  45:         {
  46:             MD5CryptoServiceProvider csp = new MD5CryptoServiceProvider();
  47:             byte[] pathBytes = csp.ComputeHash(System.Text.UTF8Encoding.UTF8.GetBytes(filePaths));
  48:             return BitConverter.ToUInt64(pathBytes, 0).ToString();
  49:  
  50:         }
  51:  
  52:         public void WriteFile(string textToWrite, string fileHash)
  53:         {
  54:             File.WriteAllText(Context.Server.MapPath(string.Format(FILE_PATH, fileHash)), textToWrite);
  55:         }
  56:  
  57:         public string CreateDatedFilePath(string filePath)
  58:         {
  59:             FileInfo fi = new FileInfo(Context.Server.MapPath(filePath));
  60:             if (fi.Exists)
  61:             {
  62:                 return fi.LastWriteTimeUtc.Ticks.ToString() + "#" + filePath;
  63:             }
  64:             return string.Empty;
  65:  
  66:  
  67:         }
  68:  
  69:         protected override void CreateChildControls()
  70:         {
  71:  
  72:             if (this.DesignMode == true)
  73:             {
  74:                 foreach (var file in CSSFiles)
  75:                 {
  76:                     string rel = file.Attributes["rel"];
  77:  
  78:                     string href = file.Attributes["href"];
  79:  
  80:                     if (rel.ToLowerInvariant() == "stylesheet")
  81:                     {
  82:                         file.Attributes["href"] = this.ResolveClientUrl(Context.Server.MapPath(href));
  83:                         this.Controls.Add(file);
  84:                     }
  85:  
  86:                 }
  87:             }
  88:             StringBuilder filePaths = new StringBuilder();
  89:             int i = 0;
  90:             foreach (var file in CSSFiles)
  91:             {
  92:                 string tagName = file.TagName.ToLowerInvariant();
  93:                 if (tagName == "link")
  94:                 {
  95:                     string rel = file.Attributes["rel"];
  96:                     string href = file.Attributes["href"];
  97:  
  98:                     if (rel.ToLowerInvariant() == "stylesheet")
  99:                     {
 100:                         string styleSheet = GetStyleSheet(href);
 101:                         if (!string.IsNullOrEmpty(styleSheet))
 102:                             combinedSheets.Append(styleSheet);
 103:                         filePaths.AppendFormat("{0}#", CreateDatedFilePath(href));
 104:                     }
 105:                 }
 106:                 else if (tagName == "style")
 107:                 {
 108:                     string inner = file.InnerHtml;
 109:                     combinedSheets.Append(inner);
 110:                     filePaths.Append("CSSSTYLE_" + i);
 111:                     i++;
 112:                 }
 113:  
 114:             }
 115:             string minimizedStyles = CssCompressor.Compress(combinedSheets.ToString(), 0, CssCompressionType.Hybrid);
 116:             string fileHash = CalculateFileHash(filePaths.ToString());
 117:             WriteFile(minimizedStyles, fileHash);
 118:  
 119:             HtmlGenericControl gen = new HtmlGenericControl();
 120:             gen.TagName = "link";
 121:             gen.Attributes.Add("href", this.ResolveClientUrl(string.Format(FILE_PATH, fileHash)));
 122:             gen.Attributes.Add("rel", "stylesheet");
 123:             this.Controls.Add(gen);
 124:         }
 125:  
 126:     }
 127: }
Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.