. Element trace obsahuje parametr „enabled“, který by měl být nastaven na 5. Dostupné z: https://msdn.microsoft.com/cs-cz/library/system.web.ui. webcontrols.sqldatasource(v=vs.110).aspx
7
2. Optimalizace webových aplikací v ASP.NET hodnotu „false“ v případě, kdy není vyžadováno sledování trasovacích informací. Pokud jsou trasovací informace nezajímavé, je zbytečné jejich sběrem zatěžovat server a tím potencionálně snižovat výkon naší webové aplikace [1].
2.3 Techniky, které vedou k optimalizovaným webovým aplikacím 2.3.1 Cacheování Jeden z nejdůležitějších faktorů při optimalizaci webových aplikací je schopnost ukládat datové objekty, stránky či části stránek do paměti již při jejich prvním získání. Tyto předměty cacheování se mohou ukládat buď na straně klienta nebo na serveru, popřípadě na cestě daného HTTP požadavku, například v proxy severu. To umožňuje předejít opakovanému získávání informací, o které již bylo dříve žádáno. Tím je šetřen procesorový čas, síťová konektivita a případně další zdroje [3]. Výhody cacheování ∙ Redukuje se čas pro získání HTTP odpovědi ze serveru ∙ Redukují se nároky na procesorový čas serveru ∙ Méně přístupů do databáze v případě, že si server databázová data cacheuje ∙ Méně odeslaných HTTP požadavků na server v případě, že je použito cacheování prohlížečem nebo cacheování na proxy serveru Cacheování umožňuje ukládat webové stránky jak na klientské, tak na serverové straně. Umožňuje také ukládat datové objekty v serverové paměti. Díky tomuto přístupu není nutno pokaždé generovat celé webové stránky při každém HTTP požadavku na server. Důsledkem je zlepšení odezvy a nižší vytížení procesoru a také databáze [1]. Cacheování je v ASP.NET velmi snadnou záležitostí, které typicky vyžaduje napsání jednoho řádku kódu pro nacacheování celé webové 8
2. Optimalizace webových aplikací v ASP.NET stránky. Na straně serveru je paměť relativně levná (pokud nebereme v úvahu častěji navštěvované aplikace, kde se využívá cacheování do souborů na disku či do dokumentové databáze) a na klientské straně nestojí vůbec nic. To dělá z cacheování velmi levný, nicméně velmi mocný nástroj pro optimalizaci webových aplikací [4]. Typy cacheování Cacheování prohlížečem Umožňuje ukládat soubory přímo v prohlížeči, tudíž není nutné pro získání těchto souborů znovu vysílat HTTP požadavek na server. Cacheovací proxy Slouží ke zrychlení odpovědi na dotaz. Při HTTP požadavku na server mohou být data odeslána již z proxy serveru, ale jen za podmínky, že stejný HTTP požadavek již daným proxy serverem prošel a při získávání dat ze servere si daný proxy server tyto data uložil do své cache. Výstupní cacheování Výstupní cacheování spočívá v tom, že výstupní data aplikace (vykreslený HTML kód, obrázek, soubor ke stažení) se ukládají pro opakované použití. Datové cacheování Snaha o uchování dat pro serverovou část (data z databází, webových služeb a jiných služeb třetích stran) tak, aby je bylo možné opakovaně použít.
Cacheování prohlížečem Server může požádat prohlížeč o nacacheování obsahu na klientském počítači skrze hlavičku odpovědi serveru „cache-control“6 . Takto nacacheované soubory v prohlížeči přináší následující výhody: ∙ Rychlé načítání souborů – prohlížeč nacacheované soubory již znovu nemusí získávat ze serveru 6. Dostupné z: https://devcenter.heroku.com/articles/ increasing-application-performance-with-http-cache-headers
9
2. Optimalizace webových aplikací v ASP.NET ∙ Snížené náklady na šířku pásma a snížení zátěže serveru – prohlížeč odešle méně HTTP požadavků na server ∙ Výborná škálovatelnost – čím větší je provoz, tím více klientských počítačů cacheuje naše data Cacheování prohlížečem zahrnuje ovšem i nevýhody: ∙ Nepředvídatelná životnost –vzhledem k tomu, že více webových stránek se snaží nacacheovat své soubory do prohlížeče na straně klienta, tak v určitém okamžiku se prohlížeč může rozhodnout, že soubory získané z daného serveru odstraní, a to z důvodu omezené velikosti přidělené paměti pro všechny webové stránky. ∙ Zastaralý obsah – je nutno reagovat na aktualizovaný obsah souborů. Vhodným řešením pro soubory obsahující obrázky, JavaScript či kaskádové styly je označení jejich verze v názvu souboru. Případně lze využít hlavičky HTTP požadavku a jejího parametru „If-Modified-Since“. Dále lze využít hlavičky HTTP odpovědi serveru zahrnující parametr „Etag“, který obsahuje hash obsahu souboru, jenž je možné využít k ověření platnosti dat uložených v cache. ∙ Bezpečnostní rizika – soubor uložený na klientském počítači může přečíst neoprávněná osoba, která má k tomuto počítači přístup.
Cacheovací proxy HTTP požadavky na server a odpovědi z něj mohou procházet skrze proxy servery na své cestě mezi serverem a prohlížečem. Tyto proxy servery mají možnost cacheování obsahu, který může být použit pro odbavení HTTP požadavků ostatních návštěvníků webových stránek. Například poskytovatel internetového připojení může používat proxy pro cacheování obsahu. Díky tomu se minimalizuje počet HTTP požadavků na server vyslaných skrze internet, jak je znázorněno na schématu (viz obr. 2.1) [4]. 10
2. Optimalizace webových aplikací v ASP.NET
Obrázek 2.1: Schéma zobrazující proxy server v síti [4]. Využití cacheovaní proxy serverem má následující výhody: ∙ Pokud proxy server ukládá soubor, zatím co daný soubor putuje ke koncovému uživateli, může tento soubor sloužit pro jiného uživatele se stejným HTTP požadavkem. Z toho plyne, že jsou obslouženi dva klienti za cenu zatížení serveru pouze jedním klientem. ∙ Rychlejší načítání souborů – geograficky je klientský prohlížeč mnohem blíže proxy serveru nežli danému webovému serveru, ze kterého se pokouší daná data získat. ∙ Stejně jako u cache prohlížeče, je také u cache proxy serveru snižována zátěž webového serveru, dále jsou snižovány náklady na šířku pásma a je zajištěna dobrá škálovatelnost. Nicméně cacheování na straně proxy serveru má i nevýhody: 11
2. Optimalizace webových aplikací v ASP.NET ∙ Bezpečnostní rizika – proxy server by mohl zaslat data určená pro specifického klienta klientovi jinému, pro nějž by tato data nemusel být určena. ∙ Proxy servery obvykle necachují soubory obsahující řetězec dotazu. ∙ Cacheování proxy serverem nelze využít v případě, pokud je v odpovědi serveru zahrnuto nastavení nějaké cookie. ∙ Stejně jako cache prohlížeče i cache proxy serveru může kdykoliv smazat již nacacheovaná data z důvodu uvolnění místa pro data z jiných webových serverů. Stejně je tomu i u aktualizovaných souborů na serveru, které se v cache aktualizovat nedají. Výstupní cacheování Výstupní cacheování umožňuje ukládat na webovém serveru celé stránky nebo jejich části. Výstupní cacheování má následující výhody: ∙ Flexibilita – podporuje ukládání různých verzí souborů pomocí řetězce dotazu, hlavičky HTTP požadavku či vlastní proměnné. ∙ Umožňuje ukládat do cache pouze části stránek. ∙ Životnost prvků v cache je předvídatelná, protože o paměť nesoupeří jiné webové stránky. To ovšem neplatí pro sdílený webový hosting, kde mnoho webových stránek používá stejný webový server. Výstupní cacheování má ovšem také nevýhody: ∙ Výstupní cacheování není vhodné pro cacheování specifických stránek pro konkrétního návštěvníka, protože je pak ukládáno velké množství stránek s minimálním využitím. ∙ Využívá se paměti nebo jiných zdrojů serveru. ∙ Je problém cacheovat mezi servery, protože se celá cache nachází pouze v paměti serveru. Například u serverových farem, kde každý server má svou vlastní cache, může vznikat duplicita dat 12
2. Optimalizace webových aplikací v ASP.NET na ostatních serverech. To vede k možné nekonzistenci mezi verzemi takto uložených souborů v jednotlivých cacheích každého serveru. Vyvarovat se problémů s nekonzistencí je možno použitím distribuované cache, kdy při změně dat jedním serverem se změněná položka v cache může stát nevalidní, a tak nekonzistence nenastane. ∙ Pokud se jedná o cache v operační paměti procesu webového serveru, tak v případě restartu webového serveru, ale také při recyklaci aplikačního poolu7 , obsah cache na serveru zmizí. Poslední dvě nevýhody mohou být řešeny přesunutím cache na oddělené cacheovací servery. Datové cacheování Datové cacheování je zaměřeno na cacheování individuálních objektů, které jsou užívány kódem v běhovém prostředí webové aplikace. Datové cacheování umožňuje ukládat dvojce klíčhodnota, které jsou přístupné typicky pro všechny HTTP požadavky na server dané webové aplikace [4]. 2.3.2 Snížení doby, po kterou se stránka načítá Jeden z kroků, který je vhodný pro zlepšení výkonu webové aplikace, je přesun funkcionality ze serveru do prohlížeče. Místo počítání výsledku či validaci formuláře na serveru je vhodné použít JavaScriptový kód, který poběží v prohlížeči. V důsledku toho méně uživatelských akcí způsobuje odeslání HTTP požadavku na server, a tím odpadá čekání na odpověď, což významně ovlivňuje zpětnou odezvu dané stránky. Nutno ovšem zmínit, že se validace na stranu klienta nepřesouvá, ale pouze duplikuje, aby se snížil počet HTTP požadavků. Vše co je odesláno na server, je opětovně validováno z důvodu bezpečnosti. Nevýhodou tohoto přístupu je, že kód se fyzicky musí dostat ze serveru do prohlížeče. To může ovlivnit dobu načítání stránky, zvláště pokud jsou použity velké JavaScriptové knihovny. Je potřeba najít jistý kompromis mezi rychlostí načítání stránky a její odezvou po načtení. Velké množství návštěvníků webových stránek danou stránku opustí, 7. Dostupné z: http://www.c-sharpcorner.com/UploadFile/225740/ introduction-to-application-pool-in-iis/
13
2. Optimalizace webových aplikací v ASP.NET pokud bude mít příliš dlouhé načítací časy [4]. Snížení doby načítání stránek umožní následující postupy: ∙ Načítání JavaScriptových souborů paralelně s ostatními zdrojovými soubory ∙ Rychlejší načítání JavaScriptu ∙ Načítání JavaScriptu na vyžádání ∙ Vyhnutí se blokaci vykreslování stránky při načítání JavaScriptu ∙ Rychlejší načítání kaskádových stylů 2.3.3 Načítání JavaScriptových souborů paralelně s ostatními zdrojovými soubory Tento krok se zaměřuje na rychlejší vykreslení webové stránky využívajícího paralelního načtení souborů s kaskádovými styly, obrázky a JavaScriptem. Při použití tohoto přístupu se kaskádové styly s obrázky načtou dříve, než doběhne načtení JavaScriptu, nebo alespoň nebude jejich načítání trvat tak dlouho po dokončení načítání JavaScriptu [4]. K tomu, aby bylo možné načítat paralelně sobory s kaskádovými styly spolu s JavaScriptem stačí nejprve načíst soubory s kaskádovými styly a až poté JavaScriptové soubory (viz obr. 2.2).
Obrázek 2.2: Příklad zápisu deklarace externích souborů, který umožňuje paralelní stahování souborů s kaskádovými styly spolu s JavaScriptem [4]. Načítání obrázků zároveň s JavaScriptem je o něco složitější, protože obrázky bývají součástí těla stránky (element v HTML kódu), tudíž jejich deklarace se nenachází v hlavičce. 14
2. Optimalizace webových aplikací v ASP.NET Aby načítání obrázku začalo před načítáním JavaScriptu, je možné použít jednoduchý JavaScriptový kód (viz obr. 2.3), který spustí načítání obrázků dříve. Tato technika se označuje jako „image preloading“ [4].
Obrázek 2.3: Příklad zápisu deklarace externích souborů, který umožňuje paralelní stahování obrázků spolu s JavaScriptem [4].
2.3.4 Rychlejší načítání JavaScriptu Dalším krokem je rychlejší načtení stejného JavaScriptového souboru, což umožní návštěvníkům stránek trávit méně času čekáním, než se stránky kompletně načtou. Existují následující techniky, které vedou k rychlejšímu načítání JavaScriptových souborů. Existují následující techniky, které vedou k rychlejšímu načítání JavaScriptových souborů: ∙ Techniky související s obrázky, jako je cacheování či paralelní stahování ∙ Použití Content Delivery Network (CDN) ∙ GZIP komprese8 ∙ Minifikace ∙ Kombinování nebo dělení JavaScriptových souborů ∙ Odstranění nepoužívaného kódu 8. Dostupné z: http://tomaserlich.cz/gzip-komprese-css-a-js/
15
2. Optimalizace webových aplikací v ASP.NET Techniky související s obrázky Stejně jako soubory s kaskádovými styly, tak i soubory s JavaScriptem jsou statické. To znamená, že mnoho technik, které lze aplikovat na obrázky, lze aplikovat i na JavaScriptové soubory, jež zahrnují cacheování a paralelní načítání. Použití Content Delivery Network Přiblížením statických souborů návštěvníkům stránek způsobí rychlejší odpovědi na HTTP požadavky. Toho lze docílit umístěním statických souborů umístěných na serverech CDN. CDN je světová síť serverů, které přibližují statický obsah webových stránek blíže návštěvníkům. Například pokud je daný webový server umístěn v Evropě a dané webové stránky bude chtít navštívit návštěvník sídlící v USA, tak pro stažení statického obsahu se využije jeden ze serverů sítě CDN, který je nejblíže tomuto návštěvníkovi. Distribuce statických souborů skrze CDN může velmi redukovat dobu stahování statických souborů, a to v případech, kdy servery CDN jsou blíže návštěvníkům daných stránek, než je tomu u daného webového serveru. GZIP komprese Webový server IIS umožňuje komprimovat obsah odeslaný do prohlížeče, jenž zahrnuje soubory s JavaScriptem a kaskádovými styly. Komprese může přinést dramatické rozdíly ve velikosti přenášených souborů. Na příkladu produkční verze knihovny jQuery můžeme vidět, jak moc se změní velikost komprimovaného souboru (viz tabulka 2.1).
jQuery v1.3.2
Bez komprese
GZIP komprese
120KB
35KB
Tabulka 2.1: Redukce velikosti knihovny při použití GZIP komprese.
Minifikace JavaScriptových souborů Aby byla zajištěna přehlednost JavaScriptového kódu, obsahují JavaScriptové soubory mnoho komentářů a bílých znaků, které jsou pro prohlížeč nadbytečné. Minifikace JavaScriptových souborů odstraní tyto nepotřebné komentáře a bílé znaky, což vede ke zmenšení těchto souborů a zkrácení doby pro jejich stažení ze serveru. Také vývojáři nemusí mít obavy, že přidáním 16
2. Optimalizace webových aplikací v ASP.NET dalších komentářů zvětší velikost daného souboru a tím zvýší nároky na přenos takto zvětšeného souboru. Některé nástroje pro minifikaci souborů zkracují i názvy proměnných. To je velmi užitečné v případě, že daný server nepoužívá GZIP kompresi. V případě, že je komprese na serveru zapnuta, zmíněné zkracování názvů proměnných bude mít jen malý vliv na zmenšení samotného souboru, protože algoritmy použity pro kompresi jsou velmi dobře vyladěny na zkracování opakujících se řetězců, jako jsou například již zmíněné názvy proměnných [4]. Dopad minifikace Jak moc velký vliv má minifikace ve srovnání s GZIP kompresí? Zde je uvedeno srovnání těchto dvou přístupů na příkladu nekomprimované knihovny jQuery ve verzi 1.3.2, kdy pro minifikaci byl použit nástroj YUI Compressor verze 2.4.2 (viz tabulka 2.2). Z výsledků vyplývá, že nejvhodnější je kombinace minifikace s GZIP kompresí. I když již samotná GZIP komprese je dosti účinná.
Neminifikovaná Minifikovaná
Bez komprese
GZIP komprese
120KB 74KB
35KB 21KB
Tabulka 2.2: Redukce velikosti knihovny při použití GZIP komprese a minifikace. Kombinování nebo dělení JavaScriptových souborů Častým krokem ke snížení doby načítání JavaScriptových souborů je kombinování více souborů do jednoho velkého souboru, díky čemuž je načítán pouze jeden velký JavaScriptový soubor. Alternativou je naopak z velkého JavaScriptového souboru udělat více malých souborů a ty načítat paralelně. Oba přístupy se vyplatí vždy v jiném případě. V okamžiku, kdy existuje velké množství jednotlivých souborů, které značně převyšuje maximální počet paralelně stahovaných souborů, jenž je dán prohlížečem, v tom případě je vhodné uvažovat o zkombinování některých souborů do jednoho velkého. Naopak, pokud počet načítaných souborů je nižší, v tom případě je vhodné větší soubory rozdělit na více menších. 17
2. Optimalizace webových aplikací v ASP.NET Mít soubory rozdělené je také vhodné v situaci, kdy je aplikace velmi rozsáhlá a ne všechny soubory se využívají na všech stránkách. Pokud běžný uživatel využije jen malou část ze všech dostupných stránek, je vhodné na to reagovat smysluplným rozdělením souborů, aby byl distribuován pouze kód, jenž dané stránky využívají. Odstranění nepoužívaného kódu Z důvodu, že JavaScriptový kód je oddělen od HTML elementů uživatelského prostředí, je velmi jednoduché zapomenout odstranit kód, který již nebude nadále třeba. 2.3.5 Načítání JavaScriptu na vyžádání JavaScriptový kód se zpravidla dělí na dvě části. Kód potřebný pro vykreslení stránky a kód, který obsluhuje uživatelské rozhraní (například události typu „click“). Kód vykreslující stránku slouží pro lepší vzhled stránky samotné a také pro napojení jednotlivých ovládacích prvků (například tlačítek). Vykreslující kód vyžaduje načtení spolu se stránkou, zatímco kód obsluhující uživatelské rozhraní může být načten teprve v okamžiku, kdy je potřeba zareagovat na nějakou událost (například zmíněnou událost typu „click“). Tím se redukuje množství načítaného kódu při pouhé návštěvě stránky. Nicméně pokud je třeba volat kód obsluhující uživatelské rozhraní, je nutno počítat se zdržením a návštěvníkovi stránek sdělit, že se kód načítá (více o možnostech jakým způsobem uživatele informovat o načítání kódu je popsáno v sekci Indikace načítání stránky). 2.3.6 Vyhnutí se blokaci vykreslování stránky při načítání JavaScriptu Idea je načíst téměř všechny skripty tak, aby neblokovaly vykreslování stránky. Důsledkem toho je dřívější zobrazení vykreslené webové stránky uživateli. Existují následující cesty jak tomuto jevu předejít, případně je třeba seznámit uživatele se vzniklou situací: ∙ Přesunutí všech HTML elementů <script> na konec stránky 18
2. Optimalizace webových aplikací v ASP.NET ∙ Oddělení vykreslovacího kódu od kódu obsluhujícího uživatelské rozhraní ∙ Indikace načítání stránky Přesunutí všech HTML elementů <script> na konec stránky Na základní úrovni je zabránění blokace vykreslování stránek velmi jednoduché. Jednoduše se přesunou HTML elementy <script> z elementu na konec elementu . Díky tomu se stránka vykreslí dříve, než element <scrtipt> dostane šanci cokoliv blokovat. Oddělení vykreslovacího kódu od kódu obsluhujícího uživatelské rozhraní Kód potřebný pro vykreslení stránky obvykle bývá mnohem menší, než je tomu u kódu obsluhujícímu uživatelské rozhraní. A abychom předešli zobrazení našich stránek v surovém stavu, je vhodné načíst kód vykreslující stránku předem. Sice bude pozdrženo vykreslování samotné stránky, nicméně v tomto případě je to žádoucí. Kód obsluhující uživatelské rozhraní se načte až nakonec, nebo jak bylo zmíněno výše, na vyžádání. Nicméně uživatel již před načtením oddělených skriptů obsahující obsluhu uživatelského rozhraní vidí ovládací prvky tohoto rozhraní, a při stisku některého z tlačítek se mu může jevit, že stránka nefunguje. Z toho důvodu je vhodné o načítání stránky uživatele informovat [4]. Indikace načítání stránky Aby byl uživatel informován, že stránka ještě není zcela načtena, je vhodné mu zobrazit indikátor načítání stránky do doby, než bude stránka v použitelném stavu. Toho lze docílit jednoduše. Stačí k tomu obyčejný element , který bude obsahovat text „Načítá se. . . “, nicméně je možné využít i sofistikovanější způsoby. Po načtení kódu stačí jednoduše tento indikátor skrýt [4]. 2.3.7 Rychlejší načítání souborů s kaskádovými styly Stejně jako JavaScript, tak i kaskádové styly blokují vykreslování stránky. To způsobuje, že návštěvník stránek vidí prvky až v jejich stylované podobě, což je žádoucí. Načítání souborů s kaskádovými styly také blokuje načítání JavaScriptových souborů, a to z důvodu možné existence 19
2. Optimalizace webových aplikací v ASP.NET referencí uvnitř JavaScriptových souborů na definice v souborech s kaskádovými styly. Je tedy žádoucí, aby soubory s kaskádovými styly byly načítány co nejrychleji. K tomu je vhodné použít následující techniky: ∙ Techniky související s obrázky, jako je cacheování či paralelní stahování ∙ Použití Content Delivery Network (CDN) ∙ GZIP komprese ∙ Kombinování nebo dělení souborů s kaskádovými styly ∙ Minifikace ∙ Odstranění nepoužívaného kódu Všechny tyto techniky již byly popsány v kapilole 2.3.4, proto jsou níže popsány pouze techniky, které se odlišují v principu samotného kódu. Minifikace Minifikace souborů s kaskádovými styly je velmi podobná jako minifikace JavaScriptových souborů. Minifikace zahrnuje odstranění nadbytečných bílých znaků a komentářů. Také je možné využít nahrazení hodnot jednotlivých vlastností za kratší zápis. Například barva s hodnotou „#ff0000“ může být nahrazena kratší hodnotou „red“. Dopad minifikace Dopad minifikace závisí na tom, zda je povolena komprese na serveru. V případě že povolena není, je dopad minifikace výrazný. V opačném případě je redukce velikosti souboru jen velmi malá [4]. Odstranění nepoužívaného kódu Protože kód s kaskádovými styly je oddělen od stránek, ve kterých je používán, je velmi jednoduché zapomenout smazat již nepoužívaná pravidla, která v souboru zbyla po odstranění HTML elementů, jež se k těmto pravidlům vázaly. 20
2. Optimalizace webových aplikací v ASP.NET Pro odhalení a zároveň pro odstranění nepotřebných selektorů v souborech s kaskádovými styly existují nástroje ve formě rozšiřujících doplňků do prohlížečů. Tyto nástroje dokáží odhalit, zda některá ze stránek nevyužívá na první pohled nepotřebný selektor, a po důkladné analýze nevyužívané selektory smaže. Příkladem těchto nástrojů je například „Dust-Me Selectors“ určen pro prohlížeč Firefox, či nástroj „CSS remove and combine“ doplněk prohlížeče Chrome [4].
2.4 Užitečné nástroje pro optimalizaci webových aplikací 2.4.1 Diagnostické nástroje klient + přenos Fiddler Jednoduchý nástroj, který se spustí na straně klienta, kde se chová jako proxy server a zachytává HTTP komunikaci [5]. YSlow Nástroj pro analýzu webových stránek, který dokáže zobrazit konkrétní příčiny pomalého běhu webových stránek a na základě získaných dat přidělí dané stránce hodnocení [6]. 2.4.2 Diagnostické nástroje webového serveru ASP.NET Přehled o tom, co se děje na serverové části nám může dát zapnuté trasování. Výstup trasovacích informací obsahuje čas strávený v jednotlivých fázích životního cyklu webové stránky, což nám umožňuje lokalizovat, kde dané zpracovávání není optimální a zda je to vůbec problém serveru. V trasovacích informacích je obsažena i velikost ViewState, která je dána jednotlivými HTTP požadavky a je možné zde odhalit, problémy právě pramenící z velké velikosti ViewState [1]. WCat Nástroj WCat dokáže paralelně spustit několik klientů, kteří budou jednotlivě generovat sekvenční zátěž na zaznamenanou sérii HTTP požadavků. Je zde možnost nastavit počet virtuálních klientů, možnost nastavit, vůči kterému serveru se bude aplikace spouštět a možnost nastavit dobu trvání daného testu [7]. 21
2. Optimalizace webových aplikací v ASP.NET RedGate ANTS Profiler Tento nástroj funguje tak, že se připojí na již běžící webovou aplikaci, případně si ji spustí sám. Po dobu připojení na danou aplikaci snímá veškerá data vyjadřující chování dané aplikace, zejména trasování kódu, a poté zobrazí počet volání jednotlivých metod a dobu, kterou daný proces v dané metodě strávil. Při nastavení detailního trasování je možné určit časovou ztrátu na úrovni řádků kódu, kdy je možné zobrazit informaci o tom, kolik milisekund se strávilo na nejdéle vykonávaném řádku kódu a jaká je procentuální hodnota této časové ztráty z celkového času po který aplikace běžela. Je nutno zmínit, že tento nástroj velmi ovlivňuje výkon samotné aplikace, tudíž z naměřených výsledků by nás měl spíše zajímat procentuální čas jednotlivých akcí nežli skutečná naměřená hodnota v jednotkách času [2]. PerfView Nástroj pro sběr informací z produkčního serveru. Na produkčním serveru si nemůžeme dovolit spustit výše zmíněný RedGate ANTS Profiler, jež zásadně ovlivňuje výkon měřené aplikace. PerfView se nijak nepřipojuje na danou aplikaci, ale jen sbírá data z událostí systému Windows, kterých je takové množství, že se můžeme dovědět srovnatelné informace jako z již zmíněného nástroje RedGate ANTS Profiler. Zpomalení serveru je tvořeno pouze vlastní režií, jež je tvořena odchytáváním dat, které se ukládají do paměti a poté na pevný disk. Čili je zde potřebné počítat s drobným zpomalením serveru, které ale většinou nebývá pro provoz nijak zásadní [2]. 2.4.3 Nástroje určeny pro bundling a minifikaci Microsoft Ajax Minifier Nástroj byl původně vytvořen jako interní nástroj společnosti Microsoft, který byl ovšem časem uvolněn pro volné užití. Jedná se o velmi efektivní nástroj pro minifikaci JavaScriptových souborů a souborů s kaskádovými styly [2]. Microsoft.Web.Optimization.dll Knihovna pro bundling a minifikaci JavaScriptových souborů či souborů s kaskádovými styly.
22
3 Framework DotVVM 3.1 Motivace pro vývoj webových aplikací ve frameworku DotVVM Součástí platformy ASP.NET jsou technologie ASP.NET Web Forms1 , ASP.NET MVC2 a ASP.NET Web API3 . Web Forms jsou v dnešní době již zastaralé, MVC a Web API se dnes typicky používají v kombinaci s populárními JavaScriptovými frameworky Angular nebo React, ovšem je zde několik problémů, se kterými tyto technologie v ASP.NET prostředí naráží. Požadavky na dnešní webové aplikace nejčastěji jsou, aby byly responsivní, atraktivní, interaktivní a aby byly načteny v co nejkratším čase. Neexistuje pádný argument, aby se každá webová stránka celá znovu načítala po triviálních operacích, jakou je například odeslání formuláře metodou POST pomocí tlačítka typu „submit“. Běžně se totiž stává, že při změně jen části webové stránky se musí celá stránka znovu překreslit, což není uživatelsky přívětivé [8]. Při těchto požadavcích brzy zjistíme, že používáním zavedených frameworků, kterými bezesporu jsou ASP.NET MVC nebo ASP.NET WebForms, není možné dostatečně naplnit výše zmíněné požadavky. Respektive možné to je, nicméně to vyžaduje značné úsilí s využitím AJAX (Asynchronous JavaScript and XML) [8]. Pokud porovnáme aplikaci, která na stisk tlačítka reaguje klasickým HTTP POST požadavkem, s aplikací, jež reakci na tlačítko odbaví pomocí JavaScriptu a AJAXového volání, je druhá varianta pro uživatele mnohem přirozenější a přívětivější. Tato druhá varianta též přenáší typicky méně dat, protože se celá stránka nestahuje znovu, nýbrž si klient se serverem pouze vymění data, která se ve stránce mají změnit, typicky ve formátu JSON nebo XML [8]. Velké množství zákazníků, kteří si chtějí nechat vyvinout webovou aplikaci, často požaduje pouze Single Page Application4 (dále jen SPA), 1. 2. 3. 4.
Dostupné z: http://www.asp.net/web-forms Dostupné z: http://www.asp.net/mvc Dostupné z: http://www.asp.net/web-api Dostupné z: http://arxiv.org/ftp/arxiv/papers/1502/1502.03530.pdf
23
3. Framework DotVVM protože nechtějí, aby se jim neustále znovu načítaly webové stránky a skripty. Při navštívení SPA se načte hlavní stránka a všechny skripty, které jsou potřeba, a poté si již klient se serverem vyměňuje data ve formátu JSON, případně si stahuje jen relevantní části uživatelského rozhraní v HTML. Data jsou typicky do HTML vkládána pomocí JavaScriptového kódu, nebo je JavaScirptem generovaná podstatná část DOM stromu. SPA může obsahovat mnoho stránek s komplexními formuláři. Tyto aplikace jsou většinou psané s využitím frameworků/knihoven, jež například jsou ReactJS, AngularJS nebo KnockoutJS5 . Na straně serveru se běžně používá ASP.NET WebAPI nebo také ASP.NET MVC v kombinaci s ASP.NET WebAPI.
Obrázek 3.1: Ukázka komunikace klient–server v případě SPA. V prvním kroku si prohlížeč stáhne potřebné soubory (HTML, CSS, JavaScript), a poté již komunikace probíhá pouhým předáváním dat ve formátu JSON.
5. Dostupné z: http://knockoutjs.com/
24
3. Framework DotVVM 3.1.1 Pro vývoj webových aplikací je nutná znalost mnoha technologií Problém dnešních aplikací psaných ve frameworcích jako je AngularJS, ale i dalších, je mnoho zbytečného JavaScripteového kódu, který ve skutečnosti nedělá nic zvláštního, pouze obsahuje volání API, které přečte odpovědi ze serveru, popřípadě zpropaguje data ze serveru do uživatelského rozhraní. Přitom většina takto psaného JavaScriptového kódu by mohla být generována. Je to problém také pro začínající vývojáře, kteří se musí naučit mnoho programovacích jazyků, mnoho frameworků, ale také znát mnoho knihoven [8]. V roce 2005, kdy jednou z předních technologií pro vývoj webových aplikací byly ASP.NET WebForms, stačila pouze znalost programovacího jazyka C# a znalost HTML. Takto vytvořené aplikace sice nebyly srovnatelné s dnešními aplikacemi, jež jsou vyvíjeny pomocí výše zmíněných frameworků, nicméně pro vývoj jednoduché webové aplikace nebylo potřebné znát tolik technologií a pro začátečníky byl vývoj velmi dobře uchopitelný [8]. Dnes vývojář musí znát některý z výše uvedených frameworků, které zajišťují běh aplikace na straně klienta, měl by použít jQuery UI, nebo jiný druh ovládacích prvků a widgetů, protože ovládací prvky v čistém HTML nejsou příliš uživatelsky přívětivé a ve většině případů nefungují přesně dle představ uživatelů. Z uvedených informací plyne, že jsou potřeba knihovny například pro komponentu „DateTimePicker“6 nebo pro vzhledově přijatelný combobox a další jiné součásti webové aplikace. Je potřebná také znalost konceptů pro vývoj v JavaScriptu (např. RequireJS). Velké množství vývojářů nerozumí JavaScriptu do hloubky, dokáží pouze deklarovat funkci a proměnnou, ale nemají přehled o tom, jak fungují objekty či prototypy. V situaci, kdy je nutno psát velké množství JavaScriptového kódu, je vhodné naučit se Typescript, pro snadnější implementaci JavaScriptového kódu. Frameworky Angular a React se bez pokročilých znalostí JavaScriptu používat téměř nedají [8].
6. Dostupné z: http://demos.telerik.com/kendo-ui/datetimepicker/index
25
3. Framework DotVVM 3.1.2 Stránkování, řazení, filtrování Pokud potřebujeme efektivní stránkování, řazení či filtrování dat z databázových tabulek, které budou zobrazeny uživateli, není vhodný způsob načíst miliony záznamů na klientskou stranu a poté je filtrovat. Zde je většinou nutné použití vlastního řešení skrze vlastní API, jež bude zahrnovat parametry jako je velikost stránky, index stránky nebo funkci například pro řazení sloupců. Alternativně je možno například využít protokol OData7 , který se snaží tento problém řešit. V případě použití protokolu OData je nuntno pro něj mít podporu ve vlastním API a také je nutno použít další knihovnu, díky které bude možné s protokolem OData pracovat na klientské straně. Navíc je nutno počítat s omezenými možnostmi například při složitějším filtrování [8]. 3.1.3 Validace Další problematikou je validace. Vše je nutno validovat na straně serveru, a to z důvodu bezpečnosti. Nicméně vhodná je i validace na straně klienta. Není ideální, aby uživatel například při odeslání formuláře čekal na odpověď ze serveru, která by mu jen oznámila, že některé z polí je nesprávně vyplněno. Z toho důvodu je vhodné doplnit validaci některých formulářů validací JavaScriptovou. Tato validace neslouží jako náhrada za serverovou, nýbrž ji jen duplikuje pro přívětivější vnímání uživatelského rozhraní [8]. Existují ovšem i situace, kdy validaci na klientovi provést není možné, například když kontrolujeme unikátnost e-mailové adresy uživatele, k čemuž potřebujeme přistupovat do databáze. Je tedy užitečné mít v aplikaci mechanismus, který umí s validačními pravidly a chybami pracovat jednotně, ať už jsou na serveru, či na klientovi. Toto opět kombinace technologií Angular a ASP.NET Web API neřeší a je nutné tento problém řešit vlastními silami [8]. 3.1.4 Zobrazení data a času Jedním z dalších častých problémů je zobrazení data a času ve formátu přirozeném pro uživatele. Bylo by vhodné, kdyby formát data a času 7. Dostupné z: http://www.odata.org/
26
3. Framework DotVVM byl formátován stejným způsobem, jak na serverové části, tak na klientské, v různých zemích s různými pravidly. K tomu účelu je možno využít knihovnu Globalize.js8 , která umí zachovat stejné formátovací pravidla na straně klienta i na straně serveru. Tato knihovna nicméně existuje v mnoha verzích a obsahuje mnoho nepříjemných chyb, které její použití zásadně ztěžují [8]. 3.1.5 Lokalizace Určité části aplikace jsou lokalizovány na serveru, kde se nacházejí nějaké RESX soubory, které obsahují přeložené texty. Je mnoho nástrojů, které po načtení RESX souboru daný text přeloží a vygenerují lokalizovaný text. Čili zde není nutné řešit vlastní způsob lokalizace. Nicméně na straně klienta je nutno vytvořit vlastní řešení. Existují sice knihovny pro lokalizaci na klientské části, nicméně je nutné je napojit na data z RESX souborů skrze nějaké API, které je opět nutné řešit vlastními prostředky [8]. 3.1.6 Vytváření vlastních komponent Ve větších aplikacích je často třeba mít vlastní komponenty, které obsahují JavaScriptový kód nebo soubory s kaskádovými styly, a tyto komponenty poté sdílet mezi několika projekty. S dnešními technologiemi je to velmi obtížné, protože je nutno zahrnout jednak serverový kód komponenty samotné, dále skripty, soubory obsahující kaskádové styly, a to vše se musí distribuovat do různých aplikací, což měla svého času poměrně dobře řešena technologie ASP.NET Web Forms. Bohužel aktuálně preferované ASP.NET MVC tento problém uspokojivě neřeší [8].
3.2 DotVVM DotVVM je open source framework kompatibilní s technologií ASP.NET. Jeho cílem je vyřešit problémy zmiňované v předcházející kapitole, a poskytnout kompletní platformu, která umožní vývoj moderních webových aplikací splňující současné nároky uživatelů, a zároveň 8. Dostupné z: https://github.com/jquery/globalize
27
3. Framework DotVVM být dostatečně jednoduchý na to, aby jej mohl používat začínající webový vývojář. Hlavní výsadou tohoto frameworku je zjednodušení vývoje webových aplikací, což má za následek rychlejší a levnější vývoj. Webová stránka obsahující komplexní formuláře může být vytvořena v řádu minut [9].
3.2.1 Princip fungování frameworku DotVVM využívá návrhového vzoru MVVM, jehož základním kamenem je ViewModel. ViewModel má dvě funkce. Předně se v něm uchovává stav uživatelského rozhraní (které označujeme jako View), například hodnoty vepsané do formulářových polí atd. Dále ViewModel obsahuje definice chování, které může uživatel vyvolat například kliknutím na tlačítko ve stránce. ViewModel a View se mezi sebou provážou pomocí tzv. data-bindingu [10]. Framework DotVVM využívá na klientské straně populární JavaScriptový framework Knockout.js, což je velmi malá knihovna využívající již zmíněný návrhový vzor MVVM na úrovni DOM HTML stránky. V prostředí Knockout.js se ViewModel implementuje v jazyce JavaScript. Vzhledem k tomu, že v prostředí ASP.NET se používá nejčastěji C#, v prostředí DotVVM se ViewModel namísto v JavaScriptu generuje v C#. DotVVM jej pak do JavaScriptu přeloží a z View vygeneruje HTML obsahující data-binding v syntaxi, které rozumí Knockout JS [11].
3.2.2 DotVVM a JavaScript Aplikace napsané pomocí frameworku DotVVM obsahují mnoho JavaScriptového kódu, nicméně z pohledu vývojáře v takových aplikacích není nutné napsat ani řádek JavaScriptu. To ovšem neznamená, že aplikace ve frameworku DotVVM nemůžou obsahovat různé modifikace komponent. Všechny výhody JavaScriptu jsou zde zachovány, nicméně již není třeba psát lehce generovatelný kód, například pro získání dat ze serverové části, nebo pro plnění a sběr hodnot z formulářových prvků v HTML stránce [12]. 28
3. Framework DotVVM 3.2.3 Použití frameworku DotVVM v praxi Fungování frameworku DotVVM lze popsat následovně. V projektu webové aplikace se nachází View (DOTHTML soubor) k němuž je navázán ViewModel, jakožto obyčejná C# třída držící stav stránky.
Obrázek 3.2: Ukázka kódu v DOTHTML.
Na prvním řádku kódu (obr. 3.2) je vidět definice, která danému View poskytuje informaci o tom, která třída je tomuto View ViewModelem. Uvnitř stránky je možno používat data binding a také je možno používat serverové komponenty (například TextBox). ViewModel obvykle dědí ze třídy DotvvmViewModelBase (viz obr. 3.3), nicméně ViewModel může být i libovolná jiná C# třída, z čehož plyne, že využití výše zmíněné dědičnosti není povinné. Jediná podmínka pro třídu ViewModel je, aby ji bylo možné serializovat do formátu JSON. Důvodem je především vlastnost technologie DotVVM, jež daný ViewModel, lepe řečeno jeho části vyžadující aktualizaci, posílá mezi klientskou stranou a serverem [12]. Poté se v dané webové 29
3. Framework DotVVM
Obrázek 3.3: Ukázka třídy ViewModel. stránce vygeneruje HTML kód s příslušnými komponentami spolu se syntaxí data bindingu výše zmíněné knihovny Knockout.js. Dále se vygenerují odkazy na potřebné skripty, jako jsou například Knockout.js a DotVVM.js. Součástí vygenerovaného HTML je také skryté pole, jenž uchovává informace o hodnotách uložených ve ViewModelu. Tyto hodnoty slouží pro opětovné načtení dat v případě, že uživatel použije „krok zpět“ ve webovém prohlížeči. Z tohoto skrytého pole se po návratu na příslušnou webovou stránku všechny předchozí hodnoty ViewModelu načtou, a uživatel poté vidí stránku přesně v takovém stavu, v jakém ji opustil [12].
30
4 Implementace Implementační část této bakalářské práce zahrnuje aplikaci na generování statických HTML souborů, dále pak změny v samotném kódu frameworku DotVVM. Zdrojové kódy aplikace na generování statických HTML souborů spolu se zdrojovými kódy frameworku DotVVM jsou součástí této práce v archivu informačního systému Masarykovy Univerzity. Implementace byla rozdělena na dvě části. První část se soustředí na statické generování HTML souborů spolu s úpravou frameworku DotVVM. Cílem této úpravy frameworku bylo vytvořit podporu pro statické HTML soubory, jež nově mohou být součástí webové aplikace, která je vytvořena pomocí frameworku DotVVM. Druhou část implementace tvoří bundling a minifikace resource souborů. Zde bylo nutné upravit framework DotVVM tak, aby umožnil vytvořit vývojářem definovaný „bundle“ (balík, jež sjednocuje více skriptů do jednoho velkého scriptu) JavaScriptových souborů a poté tento balík vhodně cacheovat.
4.1 Prostředky a použité technologie Veškerá implementace byla napsána v jazyce C# v prostředí Microsoft Visual Studio 2015. Pro bundling a minifikaci souborů byla využita knihovna Microsoft.AspNet.Web.Optimization dostupná jako „NuGet“ balíček.
4.2 Generování statických HTML souborů a modifikace frameworku DotVVM pro jejich podporu V této části kapitoly jsou popsány následující úkoly: ∙ Vytvoření aplikace generující statické HTML soubory ∙ Úprava frameworku DotVVM za účelem vytvoření podpory pro možnost implementace statických stránek ve webových aplikacích, jež jsou na tomto frameworku postaveny 31
4. Implementace 4.2.1 Vytvoření aplikace generující statické HTML soubory Prvním úkolem bylo vytvoření konzolové aplikace, jež dle předložených vstupních parametrů stáhne HTML soubory, jež jsou definovány jako statické. Mezi parametry, jež jsou nutné pro spuštění aplikace, patří cesta k souboru obsahujícímu seznam virtuálních cest ve formátu JSON, dále pak cesta, jež definuje, kam se statické HTML soubory stáhnou, předposledním parametrem je URL k běžící webové aplikaci odkud mají být soubory staženy a posledním parametrem je URL úložiště, na které bude statický obsah posléze nahrán. Po spuštění aplikace s výše zmíněnými parametry je vykonávání kódu následovné: ∙ Deserializace souboru, jež definuje seznam statických cest ∙ Stažení HTML souborů pomocí třídy „WebClient“ a její metody „DownloadString“ ∙ Modifikace samotného HTML kódu (úprava cest k resource souborům, úprava cest k ostatním stránkám webové aplikace) ∙ Uložení takto modifikovaného HTML souboru do složkové struktury 4.2.2 Úprava frameworku DotVVM za účelem vytvoření podpory pro možnost implementace statických stránek ve webových aplikacích Pro zajištění podpory pro implementaci statických HTML souborů, bylo nutné vytvořit ve frameworku DotVVM několik změn: ∙ Směrování stránek se statickým obsahem ∙ Sestavení URL odkazující na stránky se statickým obsahem ∙ Přesměrování na stránku se statickým obsahem ∙ Modifikace komponenty „RouteLink“, která slouží pro generování odkazů mezi jednotlivými stránkami 32
4. Implementace Směrování stránek se statickým obsahem V DotVVM se registrace cest neboli směrování k jednotlivým stránkám provádí v třídě implementující rozhraní „IDotvvmStartup“, jež zahrnuje metodu „Configure“. Směrování se provádí právě v této metodě spolu s registrací resource souborů. V příkladu na obrázku (obr. 4.1) je vidět, že v konfiguraci DotVVM příslušné webové aplikace se nachází objekt „RouteTable“, do nějž je možno přidat cesty k jednotlivým stránkám webové aplikace. Každá taková cesta obsahuje název, virtuální cestu, cestu absolutní a případné parametry.
Obrázek 4.1: Příklad definice směrovací cesty ve frameworku DotVVM. Úkolem zde bylo přidat do konfigurace DotVVM třídu „StaticPages“, jež stejně jako třída „RouteTable“ přijímá cesty k jednotlivým stránkám, ovšem navíc ke každé jednotlivé cestě je definováno úložiště statického obsahu těchto stránek (obr. 4.2). Tento parametr je důležitý pro další zpracování stránky v DotVVM.
Obrázek 4.2: Příklad definice směrovací cesty vedoucí ke statickému obsahu. Na obrázku je vidět, že jako první parametr je nutno zadat úložiště statického obsahu, další parametry se poté již shodují s parametry, jež jsou nutny pro definici běžné směrovací cesty ve frameworku DotVVM.
33
4. Implementace Sestavení URL odkazující na stránky se statickým obsahem Pro zajištění dosažitelnosti statických stránek bylo nutno upravit generování jednotlivých URL. Pro tento účel byla vytvořena rozšiřující třída „DotvvmRouteStaticExtended“ přepisující metodu „BuildUrlCore“ z její „rodičovské“ třídy. Tato metoda pro každou statickou cestu přidá prefix s URL k úložišti statického obsahu a zároveň při této operaci je přidán sufix „.html“, jenž určuje příponu vygenerované statické HTML stránky pomocí výše popsané konzolové aplikace.
Přesměrování na stránku se statickým obsahem Při pokusu o navštívení stránky, jež je definována jako statická, je nutno uživatele přesměrovat na úložiště se statickým obsahem. V tomto případě bylo nutno upravit třídu „DotvvmMiddleware“, jež se stará o obsloužení HTTP požadavků. V této třídě je definována metoda „Invoke“ zpracovávající jednotlivé HTTP požadavky. Uvnitř metody se zjistí, zda se HTTP požadavek snaží získat stránku definovanou jako statická, a pokud tomu tak je a zároveň se jedná o HTTP požadavek typu GET, dojde k přesměrování na úložiště, kde se konkrétní statický HTML soubor nachází.
Modifikace komponenty „RouteLink“ Komponenta RouteLink slouží k vytvoření hypertextového odkazu, který je vygenerován na základě formálního názvu dané směrovací cesty a příslušných parametrů. Úprava spočívala v modifikaci třídy „RouteLinkHelpers“, která nově přidává podporu pro implementaci statických stránek. Zde podobně jako v části „Sestavení URL odkazující na stránky se statickým obsahem“ je při generování samotného hypertextového odkazu přidán prefix s URL vedoucí k úložišti statického obsahu. Stejně tak je přidán i sufix „.html“ definující příponu statického HTML souboru. 34
4. Implementace
4.3 Bundling a minifikace resource souborů v DotVVM Tato část kapitoly se zabývá minifikací a sjednocením JavaScriptových souborů v jeden velký soubor tzv. „bundle“. Řešení této části implementace zahrnuje následující změny: ∙ Definice bundle souboru ve webové aplikaci ∙ Vytvoření bundle souboru ∙ Problémy s embedded resources1 a jejich řešení ∙ Cacheování nově vzniklého bundle souboru 4.3.1 Definice bundle souboru ve webové aplikaci Stejně jako registrace nových směrovacích cest, tak i definice bundle souboru probíhá v třídě příslušné webové aplikace implementující rozhraní „IDotvvmStartup“ uvnitř metody „Configure“.
Obrázek 4.3: Definice nového bundle souboru s parametry – název, URL suffix a pole hodnot ve formátu typu string, jež představuje názvy všech resource souborů určené k minifikaci a bundlingu. Bundle je definován třemi parametry. Tím prvním je jeho budoucí název ve formátu typu string, druhým parametrem je URL suffix, jež je určen pro prohlížeč, aby dle něj detekoval, zda nebyl bundle změněn, a nevyužíval neaktuálních souborů z cache a jako poslední parametr je nutno uvést pole obsahující názvy jednotlivých resource souborů 1. Dostupné z: http://www.codeproject.com/Articles/114997/ Embedding-and-Using-Resources-from-Net-Assembly
35
4. Implementace (obr. 4.3). Tato definice zajistí zpracování zadaných resource souborů frameworkem DotVVM, jenž sloučením těchto souborů vytvoří nový resource soubor s názvem jenž byl zadán jako první parametr definice. 4.3.2 Vytvoření bundle souboru Definice bundle souboru zaregistruje příslušné resource soubory do kolekce „ResourceBundleNames“, obsahující názvy bundleovaných resource souborů spolu s názvem výsledného bundle souboru, ve třídě „DotvvmResourceRepository“. Samotný bundling souborů probíhá ve třídě „ResourceManager“ uvnitř metody „AddScriptBundle“, kde proběhne následující sled událostí: ∙ Seřazení resource souborů dle závislostí ∙ Vytvoření virtuální cesty k bundle souboru ∙ Resource soubory určené k bundlingu budou zahrnuty do kolekce „ScriptBundle“ ∙ Resource soubory, jež určené k bundlingu nejsou, budou přidány do kolekce „requiredResources“ okamžitě, nebo po přidání bundle souboru, zde záleží na jednotlivých závislostech daných resource souborů ∙ Posledním krokem je přidání bundle souboru jako nového resource souboru 4.3.3 Problémy s embedded resources a jejich řešení Při implementaci bundlingu resource souborů se vyskytl problém s přidáním tzv. „embedded resources“ (soubory, jež jsou součástí dynamicky linkovaných knihoven) do bundle souboru. Použitá knihovna pro bundling a minifikaci „web.optimization.dll“ totiž pro registraci souborů, vyžadovala virtuální cesty k daným resource souborům. Po zjištění této skutečnosti musela být vytvořena třída „EmbeddedVirtualPathProvider“ přepisující metody rodičovské třídy „VirtualPathProvider“, jež je součástí knihovny „System.Web.dll“. Po této úpravě již bylo možno získat virtuální cestu k souborům, jenž jsou součástí dynamicky linkovaných knihoven (dll). 36
4. Implementace 4.3.4 Cacheování nově vzniklého bundle souboru Název bundle souboru obsahuje aktuální verzi DotVVM, kterou aplikace momentálně využívá a to z důvodu, aby bundle soubor po aktualizaci frameworku DotVVM zaručoval integritu dat. Dále je obsažen parametr "URL suffix", který rozlišuje verze konkrétního bundle souboru. V případě změny kteréhokoliv z těchto údajů v názvu bundle souboru bude daný soubor opětovně stažen ze serveru a uložen do cache prohlížeče. Knihovna Microsoft.AspNet.Web.Optimization bohužel dosud neposkytuje rozhraní, jež by umožnilo nastavení například maximálního stáří souboru uloženého v cache. Aktuálně je expirace takového souboru nastavena na jeden rok [13]. Nicméně lze nastavit vlastnost "Cacheability"2 , jež definuje zda, a kde se má HTTP odpověď serveru cachovat. Například lze vynutit zaslání dat ze serveru při každém HTTP požadavku, jež tyto data vyžaduje, či jen omezit místa, kde všude se cache může využívat (například pouze na serveru, či pouze na klientské straně bez využití proxy atd.).
4.4 Testování a naměřené výsledky Pro testovací účely byla vytvořena jednoduchá aplikace, jež byla nasazena na web pomocí online služby Microsoft Azure. Aplikace načte data z databáze, a poté je pouze zobrazí v dané stránce. Tato aplikace byla dále porovnávána s její předgenerovanou verzí.
2. Dostupné z: https://msdn.microsoft.com/en-us/library/w9s3a17d.aspx
37
4. Implementace
Obrázek 4.4: Graf zobrazující průběh testu nepředgenerované aplikace, která má pomalejší průměrnou dobu HTTP odpovědi a menší počet odbavených HTTP požadavků za vteřinu než aplikace předgenerovaná.
Porovnání aplikací V grafu vyjadřujícím průběh konstantního zatížení původní aplikace dvaceti uživateli po dobu jedné minuty byla průměrná doba HTTP odpovědi 0,15s a průměrný počet HTTP požadavků za vteřinu se blížil hodnotě 58 (obr. 4.4). Naproti tomu z grafu zobrazujícím stejný test, jež byl aplikován na předgenerovanou verzi aplikace, je možno vyčíst průměrnou dobu odpovědi 0.06s a průměrný počet odbavených HTTP požadavků za vteřinu téměř 74 (obr. 4.5). Průměrná doba odpovědi je v případě předgenerované verze aplikace téměř třikrát nižší v porovnání s aplikací původní. Z výsledků je patrné, že předgenerovaná verze aplikace dokáže odbavit více požadavků ve stejném čase. Další výhodou je, že takto předgenerovaný obsah šetří náklady spojené s hostingem, protože takové stránky nemusí být dynamicky generovány na serveru, ale je 38
4. Implementace možné je pouze nahrát na úložiště statického obsahu, jež jsou levná, rychlá a nemají problém s dostupností.
Obrázek 4.5: Graf zobrazující průběh testu předgenerované aplikace, jež dosahuje lepších výsledků oproti aplikaci dynamicky generované na serveru.
39
4. Implementace Jednotlivé soubory
Bundle soubor
jQuery-2.1.1.min.js knockout-latest.js DotVVM.js dotvvm.Bootstrap.all.js bootstrap.min.js script-bundle
33,9KB 27,9KB 19,8KB 10,4KB 11,6KB –
– – – – – 97,3KB
součet
103,6KB
97,3KB
Tabulka 4.1: Porovnání velikosti jednotlivých scriptů s bundle souborem. V tabulce 4.1 je znázorněn rozdíl velikosti bundle souboru oproti součtu velikostí jednotlivých JavaScriptových souborů webové aplikace dotnetcollege.cz3 . Z tabulky je patrné, že rozdíl velikosti přenesených dat není nikterak výrazný. To je z velké časti způsobeno již minifikovanými verzemi jednolivých JavaScriptových souborů původní aplikace. Důležité ovšem je, že počet HTTP požadavků na server byl rapidně snížen, a to z pěti na pouhý jeden HTTP požadavek. Do bundle souboru je samozřejmě možné zahrnout více JavaScriptových souborů, a tím ušetřit více HTTP požadavků na server. Důsledkem je snížení zátěže serveru, jenž nemusí obsluhovat jednotlivé HTTP požadavky na každý JavaScriptový soubor, ale postačí pouze jeden HTTP požadavek pro stažení celého balíku scriptů.
3. Dostupné z: https://www.dotnetcollege.cz/
40
5 Závěr Cílem teoretické části bylo seznámení se s problematikou optimalizace webových aplikací, seznámení se s dnešním vývojem webových aplikací a frameworkem DotVVM, na němž lze tyto aplikace stavět. V textu je možno se dočíst, na které body je vhodné cílit při optimalizaci webových aplikací. Jsou popsány techniky, které vedou k optimalizovaným webovým aplikacím jako je například cacheování, způsoby načítání resource souborů či bundling a minifikace. Zmíněny jsou i dostupné nástroje, jež dokáží testovat výkonové nedostatky dané aplikace. Dále v textu jsou popsány moderní přístupy k vývoji webových aplikací na platformě ASP.NET, kde jsou definovány negativní vlastnosti dnešních technologií. Následně je poté popsán samotný framework DotVVM, jenž se snaží tyto nedostatky řešit. Výsledkem implementační části je rozšíření opensource frameworku DotVVM, jenž nově podporuje definici statických stránek a dokáže uživatele na tyto statické stránky přesměrovat. Dále je obsažen samotný generátor statických stránek, který vytvoří předem definované HTML soubory se statickým obsahem. Z výsledků testů je navíc patrné, že staticky generované stránky dosahují lepších výsledků, v souvislosti s rychlostí odbavení jednotlivých HTTP požadavků, než ty dynamické. Nově také framework podporuje bundling a minifikaci resource souborů, v tuto chvíli jsou podporovány pouze JavaScriptové soubory, nicméně naplánována je i implementace bundlingu a minifikace kaskádových stylů, jež bude využívat již vystavěných mechanismů z bundlingu a minifikace JavaScriptu.
41
Literatura [1] HAKEN, Robert. Optimalizace webových aplikací ASP.NET. Wug.cz. [online]. [cit. 2016-04-12]. Dostupné z: https://www.wug.cz/ zaznamy/185-MS-Fest-2013-Praha-Optimalizace-webovychaplikaci-ASP-NET. [2] HAKEN, Robert. Optimalizace výkonu webových aplikací. Wug.cz. [online]. [cit. 2016-04-12]. Dostupné z: https://www.wug.cz/ zaznamy/102-Optimalizace-vykonu-webovych-aplikaci. [3] ASP.NET Caching. Msdn.microsoft.com. [online]. [cit. 2016-04-12]. Dostupné z: https://msdn.microsoft.com/en-us/library/ xsbfdd8c.aspx. [4] PERDECK, Matt. ASP.NET Site Performance Secrets: Simple and Proven Techniques to Quickly Speed up Your ASP.NET Web Site. Birmingham, U.K.: Packt Publishing, 2010. isbn: 9781849690690. [5] Fiddler. Telerik.com. [online]. [cit. 2016-04-12]. Dostupné z: http: //www.telerik.com/fiddler. [6] YSlow. Yslow.org. [online]. [cit. 2016-04-12]. Dostupné z: http: //yslow.org/. [7] WCat. Iis.net. [online]. [cit. 2016-04-12]. Dostupné z: https:// www.iis.net/downloads/community/2007/05/wcat-63-x86. [8] HERCEG, Tomáš. DotVVM: “Javascript” Apps With No Javascript. Channel9.msdn.com. [online]. [cit. 2016-04-12]. Dostupné z: https: / / channel9 . msdn . com / Series / NET - DeveloperDays - 2015 on-demand/dotVVM-Javascript-Apps-With-No-JavascriptTomas-Herceg. [9] DotVVM Introduction. Dotvvm.com. [online]. [cit. 2016-04-12]. Dostupné z: https : / / www . dotvvm . com / docs / tutorials / introduction/latest. [10] DotVVM ViewModels. Dotvvm.com. [online]. [cit. 2016-04-12]. Dostupné z: https : / / www . dotvvm . com / docs / tutorials / basics-viewmodels/latest. [11] DotVVM Value Binding. Dotvvm.com. [online]. [cit. 2016-04-12]. Dostupné z: https : / / www . dotvvm . com / docs / tutorials / basics-value-binding/latest.
42
LITERATURA [12] HERCEG, Tomáš. DotVVM: "javascriptové"aplikace bez javascriptu. Wug.cz. [online]. [cit. 2016-04-12]. Dostupné z: http://wug.cz/ zaznamy/282- MS- Fest- 2015- Brno- dotVVM- javascriptoveaplikace-bez-javascriptu. [13] MVC4 Bundling Cache Headers. Stackoverflow.com. [online]. [cit. 2016-04-12]. Dostupné z: http://stackoverflow.com/questions/ 13065330/mvc4-bundling-cache-headers.
43