Peter Širka
Peter Širka

Osobný blog programátora a IT nadšenca.

Čast 1: ako funguje Total.js na pozadí?

1. časť: ako funguje Total.js na pozadí?

Možno sa inšpirujete nejakou funkčnosťou v tomto blogu a možno naopak - napíšete mi, ako by ste to riešili vy a prečo. Vždy existuje niekoľko spôsosob ako urobiť/implementovať rôzne veci a ja pevne verím, že som nevybral ten najhorší spôsob. Pre neznalých v Node.js len uvediem, že každá Node.js web aplikácia obsahuje sama-v-sebe vlastný webový server.

Web server a statické súbory

Každý request podlieha na začiatku jeho spracovania malej analýze. Framework podľa URL adresy overuje, či sa jedná o súbor alebo o klasické trasovanie. Overí to veľmi jednoducho cez regulárny výraz, len skontroluje, či URL adresa obsahuje súborovú koncovku s maximálnou dĺžkou 8 znakov (dá sa to zmeniť) príklad: /img/logo.jpg alebo /app.manifest. Ak sa potvrdí, že sa jedná o statický súbor, tak framework pristupuje k takémuto requestu úplne inak.

Spracovanie statického súboru:

  • v prvom rade framework skontroluje, či framework má registrované nejaké file routes
  • ak má, tak vyhodnocuje dostupné file routes a vyhodnotenej vyvolá akciu a ďalej už nepokračuje
  • ak nemá, tak sa pozerá do internej cache, či sa tento súboru už spracoval
  • ak sa spracoval, vracia response podľa informácií z cache
  • ak sa nespracoval, tak framework overuje mapping a content-type súboru podľa jeho .extension
  • následne request na súbor podlieha ďalšej analýze, overí sa, či existuje a akú má reálnu veľkosť content-length
  • následne sa vyhodnocuje merging + compression (len .js, .css, .html) a resizing (len obrázky)
  • ak sa vyhodnotí merging, compression, či resizing tak framework spracovaný súbor uloží do /tmp/ adresára
  • následne framework overí na základe content-type, či súbor podlieha GZIP kompresii (ak je povolená)
  • potom sa zacacheuje podľa URL (kľúč) veľkosť súboru a absolútna cesta na fyzický súbor v tvare:

Cachovanie je hlavne kvôli rýchlosti a efektivite, takže podľa relatívnej URL adresy sa dá veľmi rýchlo overiť, či súbor bol spracovaný alebo nie a akú má veľkosť. Framework cache resetuje každých 7 minút (dá sa to zmeniť v configu). Zabudol som poznamenať, že v prípade resize and merge sa súbory z /tmp/ adresára nemažú a framework ich po resetovaní cache znova nespracúva (len overí či existujú v /tmp/ a ak neexistujú spracuje ich znova). V celom mechanizme je ešte implementovaná HTTP cache, či streamovanie cez content-range.

Spracovanie statických súborov sa dá v config vypnúť a zašiel som ešte trošku ďalej - v prípade, že chcete na statické súbory používať napr. NGINX a zároveň používať v Total.js napr. merging, tak framework obsahuje funkciu F.snapshot(relative_url, filename), ktorá dokáže interne vytvoriť request a zároveň jeho obsah uloží do súboru na hocijaké miesto na disku.

View engine

Pri návrhu view engine som čerpal trošku inšpiráciu z ASP.NET MVC - Razor Engine, ale dovolím si povedať, že som ho urobil sofistikovanejšie ako v tej dobe bol Razor Engine (o tom inokedy). Pri vyvolaní render view sa dejú naozaj čudné veci:

views/index.html (príklad):

View Engine načíta obsah súboru do pamäti a následne začína jeho analýza:

  • poznámka: ešte pred spracovaním obsahu je jasné, pre aký jazyk bude daný view lokalizovaný
  • algoritmus vyhľadáva všetky lokalizované texty @(Title) v celom obsahu z view
  • z každého lokalizovaného textu vytvorí malý HASH a pokúsi sa ho vyhľadať v resource (viď poznámka)
  • v prípade, že lokalizovaný text sa nachádza v resource, tak text v obsahu je nahradený textom z resource
  • v prípade, že lokalizovaý text sa nenachádza v resource, tak algoritmus ponecháva aktuálny text
  • obsah je následne podrobený HTML minifikácii (ak je povolená)
  • a potom je prenesený do algoritmu view engine compiler, ktorý oddelí statický text od dynamických hodnôt
  • dynamické hodnoty algoritmus analyzuje a snaží sa zistiť, či je ich možné "vyrenderovať" ihneď napr. @{title}
  • ak sa jedná o statický text, tak jeho hodnota je uložená do poľa v globálnej premmenej (čistí sa každých 7 minút)
  • po skončení analyzovania obsahu framework vygeneruje function a skompiluje vyparsovaný obsah
  • následne ak je RELEASE mód, tak výsledok kompilácie (funkcia) sa uloží do cache po dobu 7 minút (dá sa to zmeniť)

Hodnoty v cache statických textov:

Framework vytvorí zkompilovaný view pre každý jazyk v akom bol volaný, takže pokiaľ nie je request na daný view, tak view sa nekompiluje. Celý algoritmus je trošku sofistikovanejší, ale na predstavu vyššie uvedený popis absolútne stačí.

Poznámka: HTML minifikácia minifikuje aj inline <script> a inline <style>.


Niekedy v blízkej budúcnosti sa budem snažiť opísať ešte generovanie dynamického obsahu, ktoré obsahuje tiež sofistikované algoritmy. Hlavne popíšem ako funguje middleware, authorization, cache pre routes, aplikovanie flagov, spracovanie binárnych dát (rozujem upload) až po vyvolanie controllera.