Sdílet prostřednictvím


Vytváření sady a minifikace

Rick Anderson

Sdružování a minifikace jsou dvě techniky, které můžete v ASP.NET 4.5 použít ke zlepšení doby načítání požadavků. Sdružování a minifikace zkracuje dobu načítání tím, že snižuje počet požadavků na server a snižuje velikost požadovaných prostředků (například CSS a JavaScript).

Většina současný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č zapíše do fronty další požadavky na prostředky na hostiteli. Na následujícím obrázku karty sítě vývojářských nástrojů VE F12 zobrazují časování prostředků pož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, který čeká 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 nač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í síťovou kartu vývojářských nástrojů A S P dot NET s adresami URL žádostí o prostředky v levém sloupci a jejich časováním v pravém sloupci

Předchozí obrázek znázorňuje událost Start , která udává čas, kdy byl požadavek zařazen do fronty, protože prohlížeč omezil počet souběžných připojení. V tomto případě byl požadavek zařazen do fronty po dobu 46 milisekund a čekal na dokončení dalšího požadavku.

Svazování

Sdružování 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, což může zlepšit výkon načítání první stránky.

Následující obrázek ukazuje stejné zobrazení časování jako dříve zobrazené zobrazení O produktu, tentokrát ale s povoleným sdružováním a minifikaci.

Snímek obrazovky znázorňující kartu podrobností o časování prostředku ve 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 například odebrání zbytečných prázdných znaků a komentářů a zkrácení názvů proměnných na jeden znak. Představte si 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 sníží na následující:

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

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

Původní Renamed
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žitím sdružování a minifikace (B/M) v ukázkovém programu.

Použití B/M Bez B/M Změnit
Žádosti o soubory 9 34 256%
KB Sent 3.26 11.92 266%
Přijatá znalostní báze 388.51 530 36%
Čas načtení 510 MS 780 MS 53%

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

Ladění se sadami a minifikovaným JavaScriptem

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

  1. Vyberte kartu Skript a pak vyberte tlačítko Spustit ladění .
  2. Pomocí tlačítka assets vyberte sadu obsahující funkci JavaScriptu, kterou chcete ladit.
    Snímek obrazovky znázorňující kartu Skript vývojářského nástroje I E F 12 Jsou zvýrazněné vstupní pole Prohledat skript, sada a funkce Java Script.
  3. Naformátujte minifikovaný JavaScript tak, že vyberete tlačítko KonfiguraceObrázek s ikonou tlačítka 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 do vstupního pole Prohledat skript zadán AddAltToImg.
    Snímek obrazovky znázorňující kartu Skript vývojářského nástroje I E F 12 Pole Prohledat skript se zadaným příkazem Add Alt To lmg je zvýrazněné.

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 debug v elementu compilation v souboruWeb.config . V následujícím kódu XML je nastavená hodnota true, debug takže sdružování a minifikace jsou zakázané.

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

Pokud chcete povolit sdružování a minifikaci, nastavte debug hodnotu na false. Nastavení EnableOptimizationsWeb.config můžete přepsat vlastností třídyBundleTable. Následující kód umožňuje sdružování a minifikaci a přepíše všechna nastavení v souboruWeb.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

Pokud EnableOptimizations není true atribut debug v elementu compilation v souboruWeb.config nastaven na falsehodnotu , soubory nebudou seskupovány ani minifikovány. Kromě toho nebude použita verze souborů .min, budou vybrány úplné ladicí verze. EnableOptimizations přepíše atribut debug v elementu compilation v souboruWeb.config .

Použití sdružování a minifikace s ASP.NET Web Forms a webovými stránkami

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

V této části vytvoříme projekt ASP.NET MVC, který bude zkoumat sdružování a minifikaci. 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 metodu RegisterBundles , která se používá k vytvář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é jsou laděné nebo minifikované, ale ne .vsdoc) soubory ve složce Scripts , které odpovídají řetězci se zástupnými znaky "~/Scripts/jquery-{version}.js". U ASP.NET MVC 4 to znamená, že při konfiguraci ladění se do sady přidá souborjquery-1.7.1.js . V konfiguraci verze se přidají jquery-1.7.1.min.js . Architektura sdružování se řídí několika běžnými konvencemi, jako jsou:

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

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

  • Umožňuje použít NuGet k aktualizaci na novější verzi jQuery beze změny předchozího kódu seskupení nebo odkazů jQuery na stránkách zobrazení.
  • Automaticky vybere úplnou verzi pro konfigurace ladění a verzi ".min" pro sestavení vydaných verzí.

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.
}

Ve výše uvedeném kódu se v režimu vydání vyžádá z CDN jQuery a ladicí verze jQuery se načte místně v režimu ladění. Pokud používáte síť CDN, měli byste 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ý do požadavku jQuery v případě selhání CDN.

</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řídyInclude Bundle přebírá pole řetězců, kde každý řetězec představuje virtuální cestu k prostředku. Následující kód z RegisterBundles metody v souboru App\_Start\BundleConfig.cs ukazuje, jak se do sady přidává 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řídyIncludeDirectory Bundle je k dispozici pro přidání všech souborů v adresáři (a volitelně všech podadresářů), které odpovídají vzoru vyhledávání. Rozhraní API třídy IncludeDirectorybundle 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.

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

<!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 využívají 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. Metodu Url můžete použít k vygenerování adresy URL prostředku bez přirážky potřebné k odkazování na prostředek. Předpokládejme, že chcete použít nový atribut HTML5 async . Následující kód ukazuje, jak odkazovat na modernr 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>

Výběr souborů pomocí zástupné znaky *.

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

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

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

dir imag

V následující tabulce jsou uvedeny soubory přidané do sady pomocí zástupné kartyy:

Call Přidání souborů nebo vyvolání výjimky
Include("~/Scripts/Common/*.js") AddAltToImg.js, ToggleDiv.js, ToggleImg.js
Include("~/Scripts/Common/T*.js") Výjimka neplatného vzoru Zástupný znak je povolen pouze u předpony nebo přípony.
Include("~/Scripts/Common/*og.*") Výjimka neplatného vzoru Je povolen pouze jeden zástupný znak.
Include("~/Scripts/Common/T*") ToggleDiv.js, ToggleImg.js
Include("~/Scripts/Common/*") Výjimka neplatného vzoru Čistě zástupný segment 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ů pomocí zástupných znaků z následujících důvodů:

  • Když přidáte skripty pomocí zástupných znaků, načtou se ve výchozím nastavení v abecedním pořadí, což obvykle není to, co chcete. Soubory CSS a JavaScriptu je často potřeba přidávat v určitém pořadí (ne abecedním). 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, abyste upravili implementaci IBundleOrderer .

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

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

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

    Výběr zástupné znaky "*.css" zobrazí 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í balíčků do mezipaměti

Sady nastavují hlavičku HTTP Expires na jeden rok od vytvoření sady. Pokud přejdete na dříve zobrazenou stránku, Fiddler zobrazí, že IE neprovádí podmíněný požadavek na sadu, to znamená, že z IE nejsou žádné požadavky HTTP GET pro sady a ze serveru nejsou žádné odpovědi HTTP 304. IE můžete vynutit, aby pro každou sadu pomocí klávesy F5 podmínil 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).

Na následujícím obrázku je karta Ukládání do mezipaměti v podokně odpovědi Fiddler:

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

Požadavek
http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81
je pro sadu AllMyScripts a obsahuje pár řetězce dotazu v=r0sLDicvP58AIXN\_mc3QdyVvVj5euZNzdsa2N1PKvb81. Řetězec dotazu v má token hodnoty, který je jedinečným identifikátorem používaným k ukládání do mezipaměti. Pokud se sada nezmění, aplikace ASP.NET požádá o sadu AllMyScripts pomocí tohoto tokenu. Pokud se jakýkoli soubor v sadě změní, rozhraní optimalizace 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 a server vracející HTTP 304. Informace o tom, proč má aplikace IE9 problémy s určením, jestli byla podána podmíněná žádost, najdete v položce blogu Používání sítí CDN a Vypršení platnosti za účelem zvýš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, na výslednou sadu. 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 balíček .less NuGet bez tečky .
    Instalace NuGet bez tečky

  3. Přidejte třídu, která implementuje rozhraní IBundleTransform . 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 pomocí LessTransform transformace CssMinify a . 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ách

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

Jakmile aktualizujete jeden soubor v sadě, vygeneruje se nový token pro parametr řetězce dotazu na sadu a při příštím vyžádání stránky obsahující sadu se musí stáhnout celá sada. V tradičních přirážce, kde je každý prostředek uvedený zvlášť, by se stáhnul jenom změněný soubor. Aktiva, která se často mění, nemusí být vhodnými kandidáty pro sdružování.

Sdružování a minifikace primárně zlepšují dobu načítání požadavků na první stránku. Po vyžádání webové stránky prohlížeč ukládá prostředky (JavaScript, ŠABLONY STYLŮ CSS a obrázky) do mezipaměti, takže sdružování a minifikace nepřidá žádné zvýšení výkonu při žádosti o stejnou stránku nebo stránky na stejném webu požadující stejné prostředky. Pokud u prostředků správně nenastavíte hlavičku vypršení platnosti a nepoužijete sdružování a minifikaci, heuristika aktuálnosti prohlížečů po několika dnech označí prostředky jako zastaralé a prohlížeč bude pro každý prostředek vyžadovat žádost o ověření. 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žití sítí CDN a Konec platnosti za účelem zvýšení výkonu webu.

Omezení prohlížeče šesti současných připojení na každý název hostitele je možné zmírnit pomocí CDN. Vzhledem k tomu, že síť CDN bude mít jiný název hostitele než hostitelský web, nebudou se požadavky na prostředky z CDN započítávat do limitu šesti souběžných připojení k vašemu hostitelskému 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ěleně od jQuery. Vzhledem k tomu, že výchozí vytvořená zobrazení nemají žádný vstup a nezahrnují hodnoty, nezahrnují ověřovací sadu.

Obor System.Web.Optimization názvů je implementovaný v System.Web.Optimization.dll. Využívá knihovnu WebGrease (WebGrease.dll) pro funkce 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é