Sdílet prostřednictvím


Vytváření sady a minifikace

Rick Anderson

Sdružování a minifikace jsou dvě techniky, které můžete použít v ASP.NET 4,5 ke zlepšení doby načítání požadavků. Sdružování a minifikace zlepšuje dobu načítání snížením počtu požadavků na server a snížením velikosti požadovaných prostředků (například CSS a JavaScriptu).)

Většina aktuálních hlavních prohlížečů omezuje počet souběžných připojení na každý název hostitele na šest. To znamená, že zatímco se zpracovává šest požadavků, prohlížeč zařadí další požadavky na prostředky na hostiteli do fronty. Na obrázku níže jsou na kartách sítě nástrojů pro vývojáře IE F12 zobrazeny časování prostředků vyžadovaných zobrazením O ukázkové aplikaci.

B/M

Šedé pruhy zobrazují čas, kdy je požadavek zařazen do fronty prohlížečem čekající na limit šesti připojení. Žlutý pruh je čas požadavku na první bajt, tj. čas potřebný k odeslání požadavku a přijetí první odpovědi ze serveru. Modré pruhy zobrazují čas potřebný k přijetí dat odpovědi ze serveru. Poklikáním na prostředek získáte podrobné informace o časování. Například následující obrázek ukazuje podrobnosti časování pro načtení souboru /Scripts/MyScripts/JavaScript6.js .

Snímek obrazovky znázorňující kartu sítě nástrojů pro vývojáře A S P s adresami URL žádostí o prostředky v levém sloupci a jejich časováním v pravém sloupci

Předchozí obrázek ukazuje událost Start , která udává čas, kdy byl požadavek zařazen do fronty kvůli omezení počtu souběžných připojení v prohlížeči. V tomto případě se požadavek zařadil do fronty po dobu 46 milisekund čekajících na dokončení dalšího požadavku.

Svazkování

Bundling je nová funkce v ASP.NET 4.5, která usnadňuje kombinování nebo spojování více souborů do jednoho souboru. Můžete vytvářet šablony stylů CSS, JavaScript a další sady. Méně souborů znamená méně požadavků HTTP a to může zlepšit výkon načítání první stránky.

Následující obrázek ukazuje stejné zobrazení časování zobrazení O aplikaci zobrazené dříve, ale tentokrát s povolenou sdružováním a minifikacem.

Snímek obrazovky znázorňující kartu podrobnosti časování prostředku na vývojářských nástrojích I E F 12 Událost Start je zvýrazněná.

Minification

Minifikace provádí různé optimalizace kódu pro skripty nebo šablony stylů CSS, jako je odebrání nepotřebných prázdných znaků a komentářů a zkrácení názvů proměnných na jeden znak. Zvažte následující funkci JavaScriptu.

AddAltToImg = function (imageTagAndImageID, imageContext) {
    ///<signature>
    ///<summary> Adds an alt tab to the image
    // </summary>
    //<param name="imgElement" type="String">The image selector.</param>
    //<param name="ContextForImage" type="String">The image context.</param>
    ///</signature>
    var imageElement = $(imageTagAndImageID, imageContext);
    imageElement.attr('alt', imageElement.attr('id').replace(/ID/, ''));
}

Po minifikaci se funkce zmenší na následující hodnoty:

AddAltToImg = function (n, t) { var i = $(n, t); i.attr("alt", i.attr("id").replace(/ID/, "")) }

Kromě odebrání komentářů a nepotřebných prázdných znaků byly následující parametry a názvy proměnných přejmenovány (zkráceny):

Původní Přejmenovaný
imageTagAndImageID n
imageContext t
imageElement Mohu

Dopad sdružování a minifikace

Následující tabulka uvádí několik důležitých rozdílů mezi výpisem všech prostředků jednotlivě a používáním sdružování a minifikace (B/M) v ukázkovém programu.

Použití B/M Bez B/M Změnit
Požadavky na soubory 9 34 256%
Odeslaná znalostní báze 3.26 11.92 266%
Přijatá znalostní báze 388.51 530 36 %
Doba načtení 510 MS 780 MS 53%

Odesílané bajty výrazně snížily sdružování, protože prohlížeče jsou poměrně podrobné s hlavičkami HTTP, které se vztahují na požadavky. Snížení počtu přijatých bajtů není tak velké, protože už jsou minifikovány největší soubory (Scripts\jquery-ui-1.8.11.min.js a Scripts\jquery-1.7.1.min.js). Poznámka: Časování v ukázkovém programu používal nástroj Fiddler k simulaci pomalé sítě. (Z Fiddleru V nabídce Pravidla vyberte Výkon a pak simulujte rychlosti modemu.)

Ladění v balíčku a minifikovaném JavaScriptu

Je snadné ladit JavaScript ve vývojovém prostředí (kde je element kompilace v souboru Web.config nastaven na debug="true" ), protože javascriptové soubory nejsou seskupené nebo minifikované. Můžete také ladit build verze, ve kterém jsou soubory JavaScriptu seskupené a minifikované. Pomocí vývojářských nástrojů IE F12 ladíte funkci JavaScriptu, která je součástí minifikované sady, pomocí následujícího přístupu:

  1. Vyberte kartu Skript a pak vyberte tlačítko Spustit ladění.
  2. Vyberte sadu obsahující funkci JavaScriptu, kterou chcete ladit pomocí tlačítka assets.
    Snímek obrazovky znázorňující kartu Skript vývojářského nástroje I E F 12 Zvýrazní se vstupní pole vyhledávacího skriptu, sada a funkce Java Script.
  3. Naformátujte minifikovaný JavaScript tak, že vyberete tlačítkoObrázek znázorňující ikonu tlačítka Konfigurace Konfigurace a pak vyberete Formát JavaScriptu.
  4. Ve vstupním poli Prohledat skript vyberte název funkce, kterou chcete ladit. Na následujícím obrázku byl addAltToImg zadán do vstupního pole Prohledat skript .
    Snímek obrazovky znázorňující kartu Skript vývojářského nástroje I E F 12 Pole pro zadání vyhledávacího skriptu se zvýrazněnou možností Přidat alt do lmg.

Další informace o ladění pomocí vývojářských nástrojů F12 najdete v článku MSDN Použití vývojářských nástrojů F12 k ladění chyb JavaScriptu.

Řízení sdružování a minifikace

Sdružování a minifikace je povoleno nebo zakázáno nastavením hodnoty atributu ladění v elementu kompilace v souboru Web.config . V následujícím kódu XML je nastavena hodnota true, debug takže sdružování a minifikace je zakázána.

<system.web>
    <compilation debug="true" />
    <!-- Lines removed for clarity. -->
</system.web>

Pokud chcete povolit sdružování a minifikace, nastavte debug hodnotu na false. Nastavení Web.config můžete přepsat vlastností třídyBundleTable.EnableOptimizations Následující kód umožňuje sdružování a minifikace a přepíše všechna nastavení v souboru Web.config .

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                 "~/Scripts/jquery-{version}.js"));

    // Code removed for clarity.
    BundleTable.EnableOptimizations = true;
}

Poznámka:

Není-li EnableOptimizations atribut ladění v elementu kompilace v souboru Web.config nastaven na falsehodnotu , soubory nebudou sbalené ani minifikovány.true Kromě toho nebude použita .min verze souborů, budou vybrány úplné verze ladění. EnableOptimizationspřepíše atribut ladění v elementu kompilace v souboru Web.config.

Použití sdružování a minifikace s webovými formuláři a webovými stránkami ASP.NET

Použití sdružování a minifikace s ASP.NET MVC

V této části vytvoříme projekt ASP.NET MVC pro zkoumání sdružování a minifikace. Nejprve vytvořte nový internetový projekt ASP.NET MVC s názvem MvcBM beze změny výchozích hodnot.

Otevřete soubor App\_Start\BundleConfig.cs a prozkoumejte metoduRegisterBundles, která se používá k vytvoření, registraci a konfiguraci sad. Následující kód ukazuje část RegisterBundles metody.

public static void RegisterBundles(BundleCollection bundles)
{
     bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                 "~/Scripts/jquery-{version}.js"));
         // Code removed for clarity.
}

Předchozí kód vytvoří novou sadu JavaScriptu s názvem ~/bundles/jquery , která obsahuje všechny příslušné (které je laděné nebo minifikované, ale ne .vsdoc) soubory ve složce Scripts , které odpovídají řetězci se zástupným znakem "~/Scripts/jquery-{version}.js". U ASP.NET MVC 4 to znamená, že při konfiguraci ladění se soubor jquery-1.7.1.js přidá do sady. V konfiguraci vydané verze se přidá jquery-1.7.1.min.js . Rámec sdružení se řídí několika běžnými konvencemi, jako jsou:

  • Výběr souboru .min pro vydání, pokud FileX.min.js a FileX.js existují.
  • Výběr verze jiného než ".min" pro ladění
  • Ignoruje se soubory -vsdoc (například jquery-1.7.1-vsdoc.js), které používají jenom IntelliSense.

Výše {version} uvedená shoda se zástupným znakem slouží k automatickému vytvoření sady jQuery s příslušnou verzí jQuery ve složce Scripts . V tomto příkladu použití zástupné karty nabízí následující výhody:

  • Umožňuje použít NuGet k aktualizaci na novější verzi jQuery, aniž byste změnili předchozí kód seskupení nebo odkazy jQuery na stránkách zobrazení.
  • Automaticky vybere úplnou verzi pro konfigurace ladění a verzi .min pro sestavení vydané verze.

Použití CDN

Následující kód nahradí místní sadu jQuery sadou CDN jQuery.

public static void RegisterBundles(BundleCollection bundles)
{
    //bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
    //            "~/Scripts/jquery-{version}.js"));

    bundles.UseCdn = true;   //enable CDN support

    //add link to jquery on the CDN
    var jqueryCdnPath = "https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js";

    bundles.Add(new ScriptBundle("~/bundles/jquery",
                jqueryCdnPath).Include(
                "~/Scripts/jquery-{version}.js"));

    // Code removed for clarity.
}

V kódu výše bude jQuery požadován z CDN v režimu vydání a ladicí verze jQuery se načte místně v režimu ladění. Při použití CDN byste měli mít záložní mechanismus pro případ, že požadavek CDN selže. Následující fragment kódu z konce souboru rozložení ukazuje skript přidaný k požadavku jQuery, pokud CDN selže.

</footer>

        @Scripts.Render("~/bundles/jquery")

        <script type="text/javascript">
            if (typeof jQuery == 'undefined') {
                var e = document.createElement('script');
                e.src = '@Url.Content("~/Scripts/jquery-1.7.1.js")';
                e.type = 'text/javascript';
                document.getElementsByTagName("head")[0].appendChild(e);

            }
        </script> 

        @RenderSection("scripts", required: false)
    </body>
</html>

Vytvoření sady

Metoda třídy Include Bundle přebírá pole řetězců, kde každý řetězec je virtuální cesta k prostředku. Následující kód z RegisterBundles metody v souboru App\_Start\BundleConfig.cs ukazuje, jak se do sady přidají více souborů:

bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
    "~/Content/themes/base/jquery.ui.core.css",
    "~/Content/themes/base/jquery.ui.resizable.css",
    "~/Content/themes/base/jquery.ui.selectable.css",
    "~/Content/themes/base/jquery.ui.accordion.css",
    "~/Content/themes/base/jquery.ui.autocomplete.css",
    "~/Content/themes/base/jquery.ui.button.css",
    "~/Content/themes/base/jquery.ui.dialog.css",
    "~/Content/themes/base/jquery.ui.slider.css",
    "~/Content/themes/base/jquery.ui.tabs.css",
    "~/Content/themes/base/jquery.ui.datepicker.css",
    "~/Content/themes/base/jquery.ui.progressbar.css",
    "~/Content/themes/base/jquery.ui.theme.css"));

Metoda třídy IncludeDirectory Bundle je k dispozici pro přidání všech souborů v adresáři (a volitelně všechny podadresáře), které odpovídají vzoru hledání. Rozhraní API třídy IncludeDirectory bundle je znázorněno níže:

public Bundle IncludeDirectory(
    string directoryVirtualPath,  // The Virtual Path for the directory.
    string searchPattern)         // The search pattern.

public Bundle IncludeDirectory(
    string directoryVirtualPath,  // The Virtual Path for the directory.
    string searchPattern,         // The search pattern.
    bool searchSubdirectories)    // true to search subdirectories.

Sady se odkazují v zobrazeních pomocí metody Render (Styles.Render pro CSS a Scripts.Render JavaScript). Následující kód ze souboru Views\Shared\_Layout.cshtml ukazuje, jak výchozí ASP.NET zobrazení internetových projektů odkazují na sady CSS a JavaScriptu.

<!DOCTYPE html>
<html lang="en">
<head>
    @* Markup removed for clarity.*@    
    @Styles.Render("~/Content/themes/base/css", "~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    @* Markup removed for clarity.*@
   
   @Scripts.Render("~/bundles/jquery")
   @RenderSection("scripts", required: false)
</body>
</html>

Všimněte si, že metody Render přebíná pole řetězců, takže můžete přidat více sad do jednoho řádku kódu. Obecně budete chtít použít metody Render, které vytvoří potřebný kód HTML pro odkazování na prostředek. Tuto metodu Url můžete použít k vygenerování adresy URL prostředku bez kódu potřebného k odkazování na prostředek. Předpokládejme, že jste chtěli použít nový asynchronní atribut HTML5. Následující kód ukazuje, jak odkazovat na modernizátor pomocí Url metody.

<head>
    @*Markup removed for clarity*@
    <meta charset="utf-8" />
    <title>@ViewBag.Title - MVC 4 B/M</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width" />
    @Styles.Render("~/Content/css")

   @* @Scripts.Render("~/bundles/modernizr")*@

    <script src='@Scripts.Url("~/bundles/modernizr")' async> </script>
</head>

Použití zástupné znaky "*" k výběru souborů

Virtuální cesta zadaná v Include metodě a vzor hledání v IncludeDirectory metodě může přijmout jeden zástupný znak "*" jako předponu nebo příponu do posledního segmentu cesty. Hledaný řetězec nerozlišuje velká a malá písmena. Metoda IncludeDirectory má možnost prohledávat podadresáře.

Představte si projekt s následujícími soubory JavaScriptu:

  • Skripty\Common\AddAltToImg.js
  • Skripty\Common\ToggleDiv.js
  • Skripty\Common\ToggleImg.js
  • Skripty\Common\Sub1\ToggleLinks.js

dir imag

Následující tabulka ukazuje soubory přidané do sady pomocí zástupné cardy, jak je znázorněno na obrázku:

Zavolat Přidání souborů nebo vyvolání výjimky
Include("~/Scripts/Common/*.js") AddAltToImg.js, ToggleDiv.js, ToggleImg.js
Include("~/Scripts/Common/T*.js") Neplatná výjimka vzoru Zástupný znak je povolen pouze u předpony nebo přípony.
Include("~/Scripts/Common/*og.*") Neplatná výjimka vzoru Je povolen pouze jeden zástupný znak.
Include("~/Scripts/Common/T*") ToggleDiv.js, ToggleImg.js
Include("~/Scripts/Common/*") Neplatná výjimka vzoru Čistý segment zástupných znaků není platný.
IncludeDirectory("~/Scripts/Common"; "T*") ToggleDiv.js, ToggleImg.js
IncludeDirectory("~/Scripts/Common", "T*", true) ToggleDiv.js, ToggleImg.js, ToggleLinks.js

Explicitní přidání jednotlivých souborů do sady je obecně upřednostňované před načítáním souborů se zástupnými výjimkou z následujících důvodů:

  • Při přidávání skriptů pomocí zástupných znaků se standardně načítají v abecedním pořadí, což obvykle není to, co chcete. Soubory CSS a JavaScriptu je často potřeba přidat do konkrétního pořadí (jiné než abecední). Toto riziko můžete zmírnit přidáním vlastní implementace IBundleOrderer , ale explicitní přidání každého souboru je méně náchylné k chybám. Můžete například přidat nové prostředky do složky v budoucnu, což může vyžadovat úpravu implementace IBundleOrderer .

  • Zobrazení konkrétních souborů přidaných do adresáře pomocí načítání zástupných znaků lze zahrnout do všech zobrazení odkazujících na tuto sadu. Pokud je do sady přidán konkrétní skript zobrazení, může se zobrazit chyba JavaScriptu v jiných zobrazeních, která na sadu odkazují.

  • Soubory CSS, které importují jiné soubory, vedou k tomu, že se importované soubory načtou dvakrát. Například následující kód vytvoří sadu s většinou souborů CSS uživatelského rozhraní jQuery načtených dvakrát.

    bundles.Add(new StyleBundle("~/jQueryUI/themes/baseAll")
        .IncludeDirectory("~/Content/themes/base", "*.css"));
    

    Selektor se zástupnými znaky "*.css" přičte každý soubor CSS ve složce, včetně souboru Content\themes\base\jquery.ui.all.css . Soubor jquery.ui.all.css importuje další soubory CSS.

Ukládání do mezipaměti sady prostředků

Sady nastaví hlavičku HTTP Expires header one year from when the bundle is created. Pokud přejdete na dříve zobrazenou stránku, Fiddler zobrazí, že aplikace IE neprovádí podmíněný požadavek pro sadu, to znamená, že neexistují žádné požadavky HTTP GET z IE pro sady a žádné odpovědi HTTP 304 ze serveru. Můžete vynutit, aby IE pro každou sadu s klíčem F5 vynutil podmíněný požadavek (výsledkem je odpověď HTTP 304 pro každou sadu). Úplnou aktualizaci můžete vynutit pomocí ^F5 (výsledkem je odpověď HTTP 200 pro každou sadu.)

Následující obrázek ukazuje kartu Ukládání do mezipaměti v podokně odpovědí Fiddler:

Obrázek ukládání do mezipaměti fiddler

Žádost
http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81
je pro sadu AllMyScripts a obsahuje dvojici řetězců dotazu v=r0sLDicvP58AIXN\_mc3QdyVvVj5euZNzdsa2N1PKvb81. Řetězec dotazu v má token hodnoty, který je jedinečný identifikátor používaný pro ukládání do mezipaměti. Pokud se sada nezmění, aplikace ASP.NET požádá o sadu AllMyScripts pomocí tohoto tokenu. Pokud se nějaký soubor v sadě změní, rozhraní pro optimalizaci ASP.NET vygeneruje nový token, který zaručuje, že požadavky prohlížeče na sadu získají nejnovější sadu.

Pokud spustíte vývojářské nástroje IE9 F12 a přejdete na dříve načtenou stránku, IE nesprávně zobrazí podmíněné požadavky GET provedené pro jednotlivé sady prostředků a server vracející HTTP 304. Můžete si přečíst, proč IE9 má problémy s určením, jestli byl podmíněný požadavek proveden v blogovém příspěvku Pomocí sítí CDN a Vypršení platnosti ke zlepšení výkonu webu.

LESS, CoffeeScript, SCSS, Sass Bundling.

Architektura sdružování a minifikace poskytuje mechanismus pro zpracování zprostředkujících jazyků, jako jsou SCSS, Sass, LESS nebo Coffeescript, a použití transformací, jako je minifikace výsledné sady. Pokud například chcete do projektu MVC 4 přidat soubory .less :

  1. Vytvořte složku pro obsah LESS. Následující příklad používá složku Content\MyLess .

  2. Přidejte do projektu tečku bez balíčku NuGet .less.
    Bezútěšná instalace NuGetu

  3. Přidejte třídu, která implementuje IBundleTransform rozhraní. Pro transformaci .less přidejte do projektu následující kód.

    using System.Web.Optimization;
    
    public class LessTransform : IBundleTransform
    {
        public void Process(BundleContext context, BundleResponse response)
        {
            response.Content = dotless.Core.Less.Parse(response.Content);
            response.ContentType = "text/css";
        }
    }
    
  4. Vytvořte sadu souborů LESS s LessTransform transformací CssMinify. Do metody v souboru App\_Start\BundleConfig.cs přidejte následující kódRegisterBundles.

    var lessBundle = new Bundle("~/My/Less").IncludeDirectory("~/My", "*.less");
    lessBundle.Transforms.Add(new LessTransform());
    lessBundle.Transforms.Add(new CssMinify());
    bundles.Add(lessBundle);
    
  5. Do všech zobrazení, která odkazují na sadu LESS, přidejte následující kód.

    @Styles.Render("~/My/Less");
    

Důležité informace o sadě prostředků

Dobrou konvencí při vytváření sad je zahrnout do názvu sady předponu "bundle". Tím zabráníte možnému konfliktu směrování.

Po aktualizaci jednoho souboru v sadě se pro parametr řetězce dotazu sady vygeneruje nový token a při příštím požadavku klienta na stránku obsahující sadu se musí stáhnout úplná sada. V tradičních revizích, kde je každý prostředek uveden jednotlivě, se stáhne pouze změněný soubor. Prostředky, které se často mění, nemusí být vhodnými kandidáty pro sdružování.

Sdružování a minifikace primárně vylepšují dobu načítání požadavků na první stránku. Po vyžádání webové stránky prohlížeč ukládá prostředky do mezipaměti (JavaScript, CSS a obrázky), takže sdružování a minifikace nebudou poskytovat žádné zvýšení výkonu při vyžádání stejné stránky nebo stránek na stejném webu, které požadují stejné prostředky. Pokud u prostředků nenastavíte správně hlavičku vypršení platnosti a nepoužíváte sdružování a minifikace, heuristika prohlížečů označí heuristika aktuálnosti prostředků za několik dní a prohlížeč bude vyžadovat žádost o ověření pro každý prostředek. V tomto případě sdružování a minifikace poskytují zvýšení výkonu po požadavku na první stránku. Podrobnosti najdete v blogu Používání sítí CDN a Vypršení platnosti za účelem zlepšení výkonu webu.

Omezení prohlížeče šesti souběžných připojení na každý název hostitele je možné zmírnit pomocí sítě CDN. Vzhledem k tomu, že síť CDN bude mít jiný název hostitele než váš hostitelský web, nebudou se požadavky na prostředky z CDN počítat s limitem šesti souběžných připojení pro vaše hostitelské prostředí. CdN může také poskytovat běžné výhody ukládání balíčků do mezipaměti a ukládání do mezipaměti edge.

Sady by měly být rozdělené podle stránek, které je potřebují. Například výchozí šablona ASP.NET MVC pro internetovou aplikaci vytvoří sadu ověřování jQuery oddělenou od jQuery. Vzhledem k tomu, že výchozí zobrazení vytvořená nemají žádný vstup a neposílají hodnoty, nezahrnují ověřovací sadu.

Obor System.Web.Optimization názvů je implementován v System.Web.Optimization.dll. Využívá knihovnu WebGrease (WebGrease.dll) pro možnosti minifikace, která zase používá Antlr3.Runtime.dll.

Používám Twitter k vytváření rychlých příspěvků a sdílení odkazů. Můj popisovač Twitteru je: @RickAndMSFT

Další materiály

Přispěvatelé