Zkušenosti z vývoje WebShotteru

Na konci listopadu byla spuštěna v Česku vyvinutá služba WebShotter, která dělá navenek velmi jednoduchou věc – každý den vyfotí zadané URL a archiv screenshotů zpřístupňuje ve formě připomínající Time Machine z Mac OS. Přes jednoduchý vzhled se na implementací podílí poměrně hodně technologií a o zkušenostech s nimi se podělí Borek Bernard, autor a jeden z vývojářů celé služby. Předáváme slovo…

Než začnu psát o jednotlivých technologiích a záludnostech s nimi spojených, měli byste vědět jednu věc – WebShotter vznikal v Agiliu jako „technologický sandbox“, tj. nejen že jsme chtěli udělat službu jako takovou, ale i jsme si chtěli při jejím vývoji vyzkoušet různé technologie a postupy. Článek proto rozhodně není z kategorie „jaké nejlepší technologie zvolit pro implementaci služby typu WebShotter“, ale spíš „to a to jsme zvolili a tady jsou naše zkušenosti“. Pojďme tedy na to.

Tři hlavní části WebShotteru

WebShotter (pokud jste ještě neviděli, pro představu se můžete mrknout na nějaké demo nebo si přečíst úvodní blog post na DevBlogu) se skládá ze třech hlavních implementačních celků:

  1. Screenshotovací backend
  2. Webový frontend
  3. Komponenta zobrazující screenshoty v 3D efektu („time machine“)

Každý z nich je vytvořený v poměrně odlišné technologii (.NET, Node.js, CSS3 + JavaScript) a okolo je použito pár dalších věcí pro deployment, samotné hostování apod. K popisu je toho tedy poměrně dost, začneme webovým frontendem…

Node.js + Express + Jade

Webový frontend je udělaný v Node.js, což bylo kontroverzní rozhodnutí a v kombinaci s dalšími faktory nás poměrně dost zbrzdilo. Proč jsme si chtěli zkusit Node? Ze dvou hlavních důvodů:

  1. Pro naše další projekty je na klientovi zásadní JavaScript, proto jsme chtěli tuto technologii zkusit i na serveru.
  2. Pokud člověk sleduje dění ve světě softwarového vývoje, nelze Nodu upřít značnou pozornost, které se mu dostává, a chtěli jsme na vlastní kůži zkusit, zač je toho loket.

Jaká byla realita? Skutečně taková trochu kontroverzní. Napíšu svůj pohled na věc, který se může lišit nejen od vašeho, ale i od názoru mých kolegů :)

  • Systém modulů a balíčkovací systém npm je naprosto skvělý. Na čistě technické úrovni v podstatě k npm nemám žádné výhrady a třeba ve srovnání s NuGetem ze světa .NETu byla práce s npm daleko sympatičtější.
  • Ekosystém modulů je silnou i slabou stránkou současně. Na jednu stranu se web dělaný v Node.js plní jako nákupní košík v obchoďáku – chcete přihlašování přes Facebook a Google? npm install everyauth. Placení přes PayPal? npm install paynode a tak dále. Na druhou stranu pro většinu věcí existuje balíčků hned několik, většina z nich v oblíbené verzi 0.0.1 a téměř se dá spolehnout, že s libovolným modulem bude dřív nebo později nějaký problém. Celý ekosystém jako takový je určitě skvělá věc, jen mi zatím připadá poměrně nezralý.
  • JavaScript jako jazyk stále považuji za ne zcela vhodný pro větší aplikace. Během těch pár měsíců vývoje jsme se s ním relativně sžili, nicméně skoro jakýkoliv jiný jazyk by mi přišel lepší (C#, ale klidně i PHP). Problémem JavaScriptu je dle mého především to, že si různí vývojáři stejné věci řeší jinak (JavaScriptu chybějí některé obvyklé konstrukty a klíčová slova), nástroje a IDE mají problém s pochopením kódu, kvůli všudypřítomným callbackům se relativně špatně dohledávají chyby atd. Z mého současného pohledu je tedy JavaScript na serveru pro běžné weby tolerovatelný, ale rozhodně ne nějak excelentní. (Poznámka: Node aplikace jdou psát i v něčem jiném, např. v TypeScriptu, nicméně s tím zkušenost nemáme – WebShotter je napsaný v čistém JavaScriptu. Poznámka č. 2: mluvím skutečně o běžném webu, je možné, že Node.js je skvělý na realtime věci apod., což nehodnotím.)
  • Jako nástroj jsme používali převážně WebStorm, který nám po letmém srovnání vyšel jako nejlepší volba mezi dalšími IDE a editory. I tak je to ale spíš jednooký mezi slepými a IDE pro konvenčnější jazyky / ekosystémy jsou o poznání dál.

Pokud vás zajímá, jaké moduly WebShotter používá, jsou to tyto:

  • express – základ pro většinu Node.js webů. U takto fundamentálního modulu překvapilo, jak relativně problematický byl upgrade z jedné verze na druhou (nic nepřekonatelného, ale u takto malého projektu každé zdržení o den nebo dva nepotěšilo).
  • jade – šablonovací systém. Podle mého názoru ne zcela vhodný, protože k tvorbě HTML struktury používá signifikantní whitespace (nemám to příliš rád ani u programovacích jazyků, ale u hluboce zanořených hierarchických struktur HTML elementů je to reálný problém). Se šablonovacím jazykem jsme se moc nevybírali, Jade byla defaultní volba pro nový Express projekt a na první pohled to nevypadalo špatně, takže nemůžu posoudit, nakolik lepší nebo horší jsou alternativy.
  • everyauth – řeší nám přihlašování vlastním heslem, Facebook a Google účtem. S tímto modulem jsme řešili pár záhadných problémů, celkově je ale velmi působivé, kolik služeb třetích stran pro přihlašování podporuje.
  • moment – dobrá knihovna na práci s časem.
  • cron – spouští některé naplánované úlohy, u nás hlavně rozesílání mailů.
  • plus několik modulů na komunikaci s okolním světem (msnodesql pro komunikaci s databází, paynode pro PayPal, nodemailer pro posílání emailů apod.)

Můj celkový názor na Node.js? Kdybych stál na začátku projektu znovu a měl se svými současnými zkušenostmi rozhodnout, jakou technologii pro webový frontend použít, bylo by dost těžké poskládat argumenty, proč Node.js použít namísto tradičních serverových technologií (my bychom tíhli k ASP.NET, ale i PHP plus třeba Nette by patrně nad Nodem vyhrálo). Node.js je určitě na serveru zajímavá alternativa, ale pokud už člověk zná něco jiného, nevidím moc důvodů, proč to opouštět. Na druhou stranu, aspoň jeden projekt jsme si v tom „cool“ Nodu zkusili :)

.NET + Selenium

Snímky samotné fotí robot, což je exáč napsaný v .NETu a pravidelně spouštěný naplánovanými úlohami ve virtuální mašině. Jediná otázka byla, čím dělat samotné screenshoty, tj. jaký kousek kódu z .NETu spustit, aby výsledkem byl nějaký JPEG nebo PNG soubor uložený na disku. Zvažovali jsme následující možnosti:

Většinu z těchto věcí jsme vyzkoušeli, ale pro nás trochu překvapivě měla každá z nich větší nebo menší mouchy. Když si člověk fotí jeden konkrétní web, může třeba stačit něco jako wkhtmltopdf, ale ve chvíli, kdy začnete focení testovat na větším vzorku webů a cílem je vyfotit cokoliv, začíná se věc komplikovat. Tak například wkhtmltopdf neumí GIFy, komponenta WebBrowser se ukázala nedostatečně ovlivnitelná, PhantomJS neumí pluginový obsah, Watin fotí stránku po dílech a pak ji skládá do výsledného obrázku (problém pro animace), Selenium je pomalé a občas zabugované atd.

Takže co jsme nakonec použili? Po několika iteracích a prozkoumání skoro všech slepých uliček, které existovaly, na backendu běží Selenium doplněné o řadu podpůrných skriptů, které řeší jednak vzhled stránky samotné (určitá úprava před vyfocením, například schování scrollbarů), jednak určité technické problémy Selenia (někdy zůstane browser viset, ne vždy si po sobě uklidí dočasné soubory apod.) Browser, který zajišťuje vykreslování, je v našem případě Firefox.

Do vývoje robota šlo nakonec násobně více času, než jsme očekávali, ale jak jsem už zmiňoval, je rozdíl fotit jeden konkrétní web a nabízet univerzálně fungující službu. Byla to dobrá zkušenost.

Mimochodem, náhled se generuje taky bezprostředně při přidávání webu, a protože náš robot momentálně požadavky nezpracovává hned, ale ve frontě, museli jsme náhled na webu řešit jinak. Pokud se tedy dostanete na stránku /add-web, to, co vidíte, je ohackovaný iframe, který pouze vytváří dojem screenshotu. Chtěli jsme zde použít projekt html2canvas, ale ten nám nefungoval dobře. Zkrátka udělat screenshot webové stránky je pořád docela magie.

CSS3 transformace

Asi největší vychytávkou WebShotteru z uživatelského pohledu je procházení snímků v 3D efektu podobnému Time Machine na Mac OS. Screenshoty se samozřejmě daly uspořádat do nějaké běžné mřížky, jak je to obvyklé např. v galeriích fotek, nicméně 3D efekt jsme chtěli použít, pokud to jen trochu technicky půjde (a reakce prvních uživatelů potvrdily, že to byla dobrá volba).

Ačkoliv bych byl jako Flex / Flash vývojář schopný požadovaný efekt naimplementovat poměrně rychle, jasným zadáním bylo, že se to musí podařit v čistě webových technologiích, už třeba proto, aby se WebShotter v budoucnu dobře zobrazoval na tabletech a podobných zařízeních (technicky nám tam služba běží už dneska, ale zatím bez různých optimalizací, které budou pro dobré UX nutné). Otázka tedy zněla, půjde v současných technologiích udělat efekt Time Machine tak, aby nejen fungoval, ale byl i použitelně rychlý?

Zvažovali jsme tři přístupy k implementaci:

Vyloučit jsme hned za začátku museli jQuery animace (ty základní), které sice byly rychle hotové, ale také příliš pomalé. Implementace v Canvasu by nejspíš fungovala, a třeba jsme zvažovali, že použijeme Haxe, aby šel jeden kód zkompilovat jak pro web, tak pro Flash Player (dalo by nám to dobrý fallback pro starší browsery), ale nejrychlejší a pro web nejpřirozenější bylo nakonec použít CSS3 transformace doplněné rozumným množstvím JavaScriptu (řádově několik set řádků).

Implementace tak ve výsledku používá nejnovější prostředky dostupné na webu, což má za nepříjemný následek, že třeba Internet Explorer 9, stále aktuální verze, není plně podporována (stejně tak Chrome na Linuxu a trochu problematická je i Opera). Je to poměrně velký kompromis, ale šli jsme do něj, protože aspoň nějakou implementaci máme pro všechny browsery (když nejsou dostupné 3D transformace, použijeme pomalejší 2D, a když ani ty nejsou dostupné, obrázky se staticky napozicují a animace se nekonají) a do budoucna předpokládáme, že podpora 3D transformací bude rychle narůstat.

Windows Azure

Kompletně všechno hostujeme v microsoftím cloudu Windows Azure. Používáme tyto služby:

  • Virtual Machines (robot na dělání screenshotů)
  • Cloud Storage (vygenerované PNG soubory)
  • Cloud Service (frontend)
  • Azure SQL Database (databáze, do které přistupuje jak robot, tak webový frontend)
  • Azure Websites (administrační rozhraní)

Azure jsme zvolili z několika důvodů, pár racionálních i pár subjektivních. Především se nám líbilo, že v Azure jde hostovat skutečně všechno – soubory, databáze, weby, libovolné VM apod. Teoreticky přitom nezáleží, v jaké technologii člověk vyvíjí – Node.js aplikace jsou oficiálně podporované zcela stejně jako ASP.NET. Potom se mi subjektivně líbí, v jak jednoduchém balení Microsoft svůj cloud nabízí – management portál Azure jsem dokázal používat dřív, než bych se vůbec zorientoval v nabídce AWS, a vůbec celý ekosystém Azure se Microsoft snaží dělat rozumně „přístupně“. No a na závěr bylo důležité, že pokud člověk používá MS technologie, může startup přihlásit do programu BizSpark a v rámci něj má určitý objem Azure služeb zdarma.

Potud zní vše dobře, v praxi jsme bohužel měli smůlu, protože jsme WebShotter vyvíjeli zrovna v době, kdy záhadným, ale rovněž podstatným způsobem nefungoval oficiální microsoftí Node modul pro připojení k SQL databázi. Kdybychom WebShotter dělali o dva měsíce později, na problém bychom už nenarazili, ale takto nás bohužel řešení problémů kolem databáze stálo hodně času (nebyli jsme daleko od toho, abychom celý frontend přepsali do něčeho jiného, už na to radši ani nechci vzpomínat :). Narazili jsme i na pár dalších drobnějších problémů, například nefunkční přepínače PowerShell příkazů (pomocí nich děláme deployment) apod., ale to byly spíš drobnosti, nic nepřekonatelného.

Ačkoliv nám tedy některé aspekty Azure daly pocítit, proč u sebe stále mají nálepku „Preview“, celkově jsme s touto hostovací platformou spokojeni.

Další střípky

Na WebShotteru se použila řada dalších technologií, které zmíním už spíš letem světem, protože to byly spíš drobnosti nebo podpůrné záležitosti:

  • ASP.NET Dynamic Data – dobře posloužily pro rychlou tvorbu administrace (zvažovali jsme ještě Adminer, ale tam byl problém s rozchozením proti Azure SQL Serveru a radši jsme použili něco, co fungovalo hned).
  • Loggly – příjemná služba pro logování. Zvažovali jsme ještě Papertrail a Splunk Storm, ale s Loggly bylo nejjednodušší začít (samotné procházení logů bohužel nemají udělané moc komfortně, takže pro větší projekty bych určitě zvážil alternativy).
  • PowerShell – děláme pomocí něj build a deploy.
  • Git, BitBucket – BitBucket nabízí privátní repozitáře zdarma.
  • Google Apps – náš současný SMTP server, brzy přejdeme na SendGrid pro spolehlivější doručování.
  • JIRA – dělba práce nám velmi dobře fungovala přes JIRU. Ten software jsem ještě tak rok, dva zpátky doslova nenáviděl, ale ušel ohromný kus cesty a společně s GreenHopperem (virtuální nástěnka) je to překvapivě dobře použitelný a užitečný nástroj.

Pár netechnických poznámek závěrem

Na WebShotteru bylo pro mě osobně nejpoučnější, jak velký rozdíl může být mezi původním odhadem a reálným časem potřebným k implementaci. WebShotter měl být původně projekt na dvoudenní hackaton, ale když se má služba odladit a dotáhnout až do produkce, je to skutečně o něčem jiném. S WebShotterem se nám stalo, že jsme téměř od začátku měli „90 % hotovo“, ale těch zbývajících „deset“ procent ne a ne přijít. I dnes máme poměrně dlouhý backlog a řadu nápadů, co by se dalo vylepšit, ale produkt někdy ven musel a platí staré známé done is better than perfect.

Prosba závěrem – pokud WebShotter zkusíte používat a narazíte na něm na jakékoliv problémy, dejte nám prosím vědět (třeba na borekb@gmail.com nebo přes feedback form). V tomto článku jste viděli, že je služba poskládána skutečně z mnoha různých kostiček a zazlobit může každá. :)

Komentáře: 35

Přehled komentářů

Jakub Mrozek K Node.js
Borek Bernard Re: K Node.js
Tany Re: K Node.js
Martin Kučera realizace záměru vs. technologické hračičkování
baggz Re: realizace záměru vs. technologické hračičkování
Borek Bernard Re: realizace záměru vs. technologické hračičkování
marek Re: realizace záměru vs. technologické hračičkování
Borek Bernard Re: realizace záměru vs. technologické hračičkování
marek Re: realizace záměru vs. technologické hračičkování
liborse Re: realizace záměru vs. technologické hračičkování
Martin Kučera Re: realizace záměru vs. technologické hračičkování
Čelo Re: realizace záměru vs. technologické hračičkování
Futrál Archive.org
Jakub Mrozek Re: Archive.org
Jakub Mrozek Re: Archive.org
Borek Bernard Re: Archive.org
Futrál Re: Archive.org
espinosa_cz Firefox Screenshoter
Borek Bernard Re: Firefox Screenshoter
espinosa_cz Re: Firefox Screenshoter
Borek Bernard Re: Firefox Screenshoter
espinosa_cz Re: Firefox Screenshoter
Martin Hassman Re: Firefox Screenshoter
espinosa_cz Re: Firefox Screenshoter
Borek Bernard Re: Firefox Screenshoter
Futrál Re: Firefox Screenshoter
HSN Screenshotovaci sluzba pro inhouse pouziti
Borek Bernard Re: Screenshotovaci sluzba pro inhouse pouziti
koudejak Re: Screenshotovaci sluzba pro inhouse pouziti
Čelo Re: Screenshotovaci sluzba pro inhouse pouziti
Ondřej Kučera Re: Screenshotovaci sluzba pro inhouse pouziti
HSN Re: Screenshotovaci sluzba pro inhouse pouziti
HSN Re: Screenshotovaci sluzba pro inhouse pouziti
Futrál Re: Screenshotovaci sluzba pro inhouse pouziti
HSN Re: Screenshotovaci sluzba pro inhouse pouziti
Zdroj: https://www.zdrojak.cz/?p=3751