Hugo - Staattinen sivugeneraattori

Kun Aluparkin verkkosivuja uudistettiin syksyllä 2015 päätavoitteena oli saada sivuille blogi. Lisäksi haluttiin jakaa vanha pitkä etusivu useammaksi alasivuksi.

Vanhat sivut oli toteutettu artesaanihengessä lähes täysin staattisella HTML:lla. Dynaamista toiminallisuutta edusti 24 riviä JavaScriptiä, joka uudelleenjärjesti ukkojen naamat satunnaisesti. Preprosessointipuolella oli käytössä Gulp, SASS ja Bower.

Uudet verkkosivut

Uusin verkkosivujen toteutusvaihtoehtoja vertaillessa esillä olivat seuraavat vaihtoehdot:

  • Käsintehty HTML. Liian työläs ylläpitää vaikka siihen ottaisikin kevyet template-ominaisuudet mukaan PHP:n avulla.
  • Wordpress. Luonteva vaihtoehto, koska se on osa Aluparkin tarjontaa. Toisaalta meillä ei ollut tarvetta suurimmalle osalla sen toimintoja. Wordpress toisi välttämättä myös mukanaan vaatimuksen PHP:lle ja tietokannalle, jotka taas asettavat vaatimuksia hostaukselle. Lisäksi Wordpress vaatii säännöllisesti tietoturvapäivitysten asentamista.
  • Staattiset sivugeneraattorit (static site generator). Generaattoria käytettäessä sisältö kuvataan käyttäen jotakin kuvauskieltä ja tästä kuvauksesta muodostetaan staattinen HTML-sivusto, joka voidaan sitten siirtää palvelimelle. Meillä oli ennestään kokemusta sivugeneraattoreista henkilökohtaisista blogiprojekteista. Niissä yhdistyvät yksinkertaisuus ja monipuolisuus ja ne voidaan hostata helposti. Generaattori vähentää manuaalisen työn määrää suhteessa käsin tehtyyn HTML:ään.

Edellisten pohdintojen perusteella päädyttiin sivugeneraattorin käyttöön ja sen valinnalle annettiin seuraavat vaatimukset:

  1. Sisältöä pitää pystyä tuottamaan Markdownilla
  2. Mahdollisimman vähän riippuvuuksia
  3. Sivugeneraattorilla tulee olla olemassa oleva käyttäjäkunta, dokumentaatio ja roadmap
  4. Sivugeneraattorin käytön pitää alun jälkeen vähentää työmäärää

Sivugeneraattorin valinta

Hyvä lista staattisia sivugeneraattoreita löytyy sivustolta staticsitegenerators.net. Järjestimme listan GitHub-tähtien mukaan ja valitsimme vertailuun TOP-10:stä seuraavat: Jekyll, Hugo ja Metalsmith. Vertailu suoritettiin lähes yksinomaan dokumentaatioon ja muiden kokemuksiin perustuen.

Jekyll on tähtien määrässä mitattuna suosituin staattinen sivustogeneraattori. Jekyll on toteutettu Rubylla ja pääsyy Jekyllin putoamiselle jatkosta oli aiemmat huonot kokemukset Rubyn riippuvuuksienhallinnasta. Emme myöskään halunneet valita “ilmiselvää” vaihtoehtoa. Jekyll kärsii ilmeisesti melko heikosta suorituskyvystä eli sivuston kääntäminen saattaa kestää jopa minuutteja.

Metalsmith edustaa sivugeneraattoreiden minimalistista koulukuntaa. Se on käytännössä JavaScriptillä toteutettu “plugin pipeline”, jossa eri plugineita (markdown, permalinks, layouts jne.) yhdistetään ketjuksi, joka tuottaa Markdown-lähdetiedostoista valmiin HTML-sivuston. MetalSmithissä kiehtoi sen yksinkertaisuus ja tuttu ohjelmointikieli, mutta toisaalta se tuntui liiankin kevyeltä ratkaisulta. Pelkona oli, että joutuisimme toteuttamaan sen päälle paljon sivugenerointiinkin liittyvää logiikka. Metalsmith jäi ehdottomasti mieleen ja voisin hyvin kuvitella käyttäväni sitä esim. jonkin tuotedokumentaation tai käyttöohjeen generointiin.

Hugo on Go-ohjelmointikielellä toteutettu sivugeneraattori, joka ainakin aluksi pyrki kopioimaan Jekyllin toiminnallisuuden. Hugolla on hyvä dokumentaatio ja ilmeisen vakaasti kasvava käyttäjäkunta. Hugon asennus OS X -ympäristössä on erittäin kivutonta (brew install hugo). Hugo suhtautuu vakavasti suorituskykyyn ja pyrkii pitämään kääntämiseen kuluvan ajan niin lyhyenä, että se voidaan mitata millisekunneissa (alupark.fi -sivusto kääntyy 44 millisekunnissa). Fredrik Loch on vertaillut Jekyllin ja Hugon suorituskykyä blogissaan ja näistä kahdesta Hugo erottuu selkeänä voittajana.

Hugo käytännössä

alupark.fi lähdekoodi löytyy BitBucketista. Sivuston kääntämiseen tarvitaan Hugo ja gulp (kts. README.md).

Hugo työnkulku

Hugossa sisällön perusrakenne on content/CONTENT-TYPE/ITEM.md eli esim. tämä blogikirjoitus on lähdekoodissa content/blog/2015-12-23-Hugo.md. alupark.fi -sivuston konfiguraatiossa määritellään, että sisältötyyppi blog käyttää osoiterakennetta /blog/:year/:month/:slug/, joten tästä blogikirjoituksesta generoidaan sivu blog/2015/12/Hugo/index.html. Hugo on ensisijaisesti blogigeneraattori, mutta soveltuu hyvin myös muiden sellaisten sivujen rakenteeseen, jotka noudattavat “joukko ja sen osan” -rakennetta eli erilaiset tuotetietokannat ja listaukset. Jos sen sijaan halutaan erilaisia sivupohjia eri sivuille, joudutaan hieman venyttämään käsitteistöä. Käytännössä jokainen alupark.fi -sivuston sivu blogin ulkopuolella (Ihmiset, Palvelut, Yhteys jne.) määrittelee oman sisältötyyppinsä ja sille on omat sivupohjansa. Asian yksinkertaistamiseksi varsinainen sisältökin on näillä sivuilla enimmäkseen sivupohjassa eli sivupohjassa ei käytetä Markdown-tiedostosta generoitua sisältöä.

Sivut generoidaan perutuen layouts -hakemistossa oleviin sivupohjiin. Hugossa oli alunperin tuki vain Go-sivupohjille, joita alupark.fi -sivullakin on käytetty, mutta nykyään tuetaan myös Ace- ja Amber-sivupohjia. Jokaiselle sisältötyypille on olemassa sekä listaussivun että yksittäisen sisällön sivupohja. Sivupohjissa on luonnollisesti tuki myös koostamiselle eli sivupohjien yhteiset osat voidaan erottaa omaan partials -hakemistoonsa.

Tietoa voidana ylläpitää myös tietorakenteina (YML, JSON, TOML) data -hakemistossa ja sisällyttää sieltä sivupohjiin. alupark.fi -sivustolla palvelut on mallinnettu tietorakenteina, josta Palvelut-sivu sitten koostetaan.

name: Asiantuntijat
description: |
    Tarjoamme asiantuntijoita sekä lyhyt- että pitkäaikaisiin toimeksiantoihin....
buzzwords:
    - Kehittäjä
    - ....
image: /images/services/experts.jpg

Hugo tukee myös teemoja, mutta niitä ei ole käytetty alupark.fi -sivustolla. Käytännössä teemat luovat rinnakkaisen rakenteen layout -hakemistolle ja käytettävä teema voidaan antaa joko parametrina hugo -komennolle tai määrittää se konfiguraaatiossa.

Loppusanat

Sivugeneraattoreiden laajemman käytön teknologiaskenen ulkopuolella estävät integroidun graafisen editorin puute ja sivujen palvelimelle siirtämiseen liittyvät haasteet. GitHubista löytyy projekteja, joissa näitä ongelmia on yritetty ratkaista, mutta mielestäni se ongelma on jo ratkaistu perinteisillä CMS-järjestelmillä kuten Wordpress.

Staattisen sivugeneraattorin paras puoli on muun ohjelmoinnin kanssa hyvin yhtenevä käsitemalli eli käyttäjä muokkaa versionhallinnassa olevaa lähdekoodia ja tietokone kääntää siitä valmiin lopputuloksen. Tämä putkimalli mahdollistaa erilaisten automaattisten työnkulkujen rakentamisen yksinkertaisesti. Esimerkiksi master-haaraan pushaaminen voisi laukaista sivuston päivittämisen kääntämisen ja päivittämisen palvelimelle. Lisäksi blogikirjoituksista voidaan tehdä pull requestien avulla muulle tiimille katselmoitavaksi. Itselleni on myös tärkeää, että editointia voi tehdä täysin offline-tilassa ja lopputuloksen pystyy kuitenkin näkemään reaaliaikaisesti omalla koneella. Hugon generaattori on erittäin nopea ainakin kevyellä sivumäärällä ja sitä on mukava käyttää esim. BrowserSyncin kanssa, kun sivu päivittyy sitä mukaa, kun sitä muokataan.