Hugo: moje první zkušenost s generátorem statických webů

Nedávno jsem předělával jeden web běžící tehdy na starém Drupalu 6. Po zvážení náročnosti migrace a četnosti aktualizací obsahu jsem dospěl k názoru, že není třeba mít redakční systém. Rozhodl jsem se vyzkoušet některý z populárních generátorů statických webů. A skončil jsem u Hugo.

Původní plán upgradu zmíněného webu byl takový, že si vyzkouším napsat migrace z Drupalu 6 na Drupal 8. Když jsem zjistil, že to sice není složité, ale dosti otravné, měl jsem po náladě. Daný web nemám jako výdělečný projekt, je to spíše zábava. Zvážil jsem všechna pro i proti, dospěl jsem k názoru, že aktualizací obsahu tam není tolik, aby potřebovaly redakční systém.

Zahodil jsem rozpracovaný Drupal s vlastním vzhledem a začal od začátku. Který generátor statických webů použiju? První na ráně byl samozřejmě Jekyll. Jenže mám z dřívějška nějaké obavy z Ruby a gemu, už se mi několikrát stalo, že se v počítači nějak pošašily verze a aplikace nefungovaly.

Z podobných důvodů jsem zatrhl Gatsby. Vím, JAMstack, React a tyhlety věci jsou značně populární. Ale nepotřebuju stavět pyramidu a instalovat hromadu JS věcí do počítače kvůli jednoduchému webu. To jsem mohl zůstat u Drupalu.

Nakonec tedy padla volba na Hugo. Jednak kvůli deklarovavé (a opravdu taková je) rychlosti, jednak proto, že celý ten nástroj je vlastně jeden spustitelný soubor. Instalace na macOS je hračka. Navíc se pomalu učím jazyk Go, ve kterém je Hugo napsaný. Takže o důvod více do něj zabřednout.

Hugo - generátor statických webů

První setkání s Hugo a náraz do zdi

Hugo jsem si stáhl dle instrukcí, nainstaloval, rozběhl základní kostru s nějakým tématem vzhledu a začal studovat dokumentaci. A to byl první kámen úrazu. Dokumentace k Hugo mi sice i nyní přijde hezky zpracovaná. Stejně jako při prvním otevření. Jenže jakmile začnete stavět něco konkrétního, možná narazíte jako já.

Vytvořil jsem soubory v markdownu pro obsah stránek. Jenže já potřeboval něco jako typy obsahu v Drupalu. Články a záznamy do katalogu na webu. Plus běžné stránky typu O nás. Výpisy těchto položek. Různě seřazené. V každém obsahu nějaké pokročilejší formátování než jen textový sloupec. Něco jako bloky. Přece nebudu ručně psát HTML do markdownu.

Nakonec jsem se na tom všem zasekl. Jistě, v dokumentaci vše najdete. Někdy ne do detailu, někdy ne úplně srozumitelně, ale je to tam. Je tam i mnohem více. Jenže to předpokládá, že víte, nač se ptáte. Že například nebudete hledat alternativu pro bloky v Drupalu, ale pro shortkódy z WordPressu.

Byl jsem z toho nešťastný a chvíli si hrál zpátky s Jekyllem…

Tento bezplatný videokurz pomůže i vám

Ale jak už to bývá, úplnou náhodou jsem narazil na nějaký článek od Mike Dane. Z něj jsem se dostal na jeho YouTube kanál a nakonec jsem strávil pěkný čas sjížděním jeho seriálu o generátoru statických webů Hugo.

Mike to má velice pěkně zpracované. Krok za krokem vás provede zprovozněním generátoru i zabudovaného serveru. Přidáváním jednotlivých typů obsahu, stavbou výpisů, vzájemným prolinkováním přes kategorie a mnohými dalšími možnostmi, které vám Hugo dává k dispozici.

Doporučuji na webu tohoto lektora mrknout. Má tam totiž další seriály i o Jekyllu, Gatsby, ale třeba o C, C++, Ruby, Pythonu, MongoDB a jiných věcech, se kterými se vývojář dnes setká.

Po shlédnutí všech dvaadvaceti lekcí jsem byl připraven pustit se do práce. Věděl jsem, že teď už to půjde. Mike sice neprobírá všechno, vynechává práci se zdroji a obrázky, neřeší moc CSS a JavaScript, nevěnuje se vytvoření menu. Ale to jsou už věci, které zvládnete za pomoci internetu dohledat.

Několik zádrhelů, které jsem řešil

Web jsem nakonec postavil na zakoupené HTML šabloně. Jakkoli toto řešení nemám rád a musel jsem nakonec věnovat nějaký čas odstranění nepotřebného balastu. O tom ale někdy příště. Zpět k Hugo.

Základní kostra baseof.html, rozhození na hlavičku, patičku a další součástky, to jsem zvládl bez problémů. Díky výše uvedenému seriálu, jsem si v Hugo připravil i jednotlivé typy obsahu, použil jsem shortcodes k tomu, abych lépe naformátoval obsah zadávaný do markdown souborů.

A pak jsem začal řešit několik zbývajících zádrhelů. Stručně je zde vypíšu, třeba by mohly někomu pomoci.

Jak na formátovaný obsah uvnitř shortcode? Práce s parametry shortkódu je jasná. Vypsání obsahu mezi značkami daného shortkódu taky, potíž je v tom, že už se neformátují markdownem. Jenže co když nechcete do zadání shortcode v obsahovém souboru psát HTML? Řešením je nahradit v šabloně základní {{ .Inner }} za {{ .Inner | markdownify }}.

Jak formátovat URL adresu v Hugo? Přes parametr v shortkódu předávám do jeho šablony URL adresu. Celou s http na začátku. To je fajn pro vygenerování odkazu, méně už pro jeho viditelnou část, kde http zobrazovat lidem nechci. Hugo dovede URL parsovat, takže z https://www.maxiorel.cz uděláte www.maxiorel.cz následovně: {{$url := urls.Parse (.Get "web")|}}{{ $url.Host }}.

Jak vložit HTML šablonu do jiné? Potřeboval jsem v některých místech obsahových šablon vkládat kus HTML kódu z jiného souboru. Velice jednoduše takto: {{- partial "copy.html" . -}}.

Jak na Hugo a obrázky? Práci se zdroji nevysvětluje Mikeův tutoriál, ale najdete ji popsánu coby práci se zdroji stránky v dokumentaci k Hugo. Pro mě ale nebylo na první pohled jasné, co mám udělat k tomu, abych dostal obrázek uvedený ve front matter v markdownu do HTML šablony. Řešení je přitom prosté. Pro stránku, článek či jiný obsah nedělejte jen soubor muj-clanek.md, ale vytvořte složku muj-clanek, v ní soubor index.md a do stejné složky dejte i obrázek k článku.

Ve front matter pak budete mít něco takového:

---

title: "Můj článek"

date: 2019-08-05T16:02:07+02:00

draft: true

resources:

- src: "obrazek.jpg"

  name: mainphoto

- src: "fotka-1.jpg"

  name: gallery

- src: "fotka-2.jpg"

  name: gallery

---

Donec id elit non mi porta gravida at eget metus. Curabitur blandit tempus porttitor. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Nullam quis risus eget urna mollis ornare vel eu leo. Sed posuere consectetur est at lobortis.

K tomu budete mít HTML šablonu vypisující obsah klasicky přes {{.Content}} a někde v ní byste rádi vypsali HTML značku pro napojené obrázky. Jednu pro obrázek označený jako mainphoto, druhou pro všechny fotky označené jako gallery. Všechny obrázky budou ve stejné složce jako MD soubor s obsahem článku.

První případ použijte .Resources.GetMatch, který vrací první výsledek. Já jsem rovnou využil toho, že Hugo dovede obrázky zmenšit na požadovaný rozměr. Více funkcí pro manipulaci s nimi opět najdete v dokumentaci. Tam už je to srozumitelné.

{{ with .Resources.GetMatch "mainphoto" }}
{{ $img := .Fill "770x500" }}
{{ $imgRetina := .Fill "1540x1000" }}
<img class="img-full" src="{{ $img.RelPermalink }}" srcset="{{ $imgRetina.RelPermalink }} 2x" alt="{{.Title}}" loading="lazy">
{{ end }}

Z jednoho obrázku jsem tedy Hugem udělal dvě různé velikosti a vypsat jsem odkazy na tyto soubory do šablony.

Podobně mohu projít všechny fotky do galerie, zde jen místo .Resources.GetMatch použiju .Resources.Match.

{{ with .Resources.Match "gallery" }}
  {{ range . }}
    {{ $img := .Fill "134x134" }}
    {{ $imgRetina := .Fill "268x268" }}
    <li class="work_img"><a href="{{ .RelPermalink }}"><img src="{{ $img.RelPermalink }}" srcset="{{ $imgRetina.RelPermalink }} 2x" alt="{{.Title}}" class="img-full" loading="lazy"></a></li>
  {{ end }}
{{ end }}

Jak vložit v Hugo assety spolu s jejich minifikací a otiskem? Hugo podporuje pomocí své pipeline i SASS a další pre- a post procesory CSS a javaScriptu. Pro moje účely však stačila jednoduchá minifikace těchto souborů. Prvním krokem je jejich správné umístění. Nakopírujete je do složky assets ve svém tématu vzhledu.

V HTML šabloně pak použijete následující zápis:

{{ $js := resources.Get "js/script.js" | resources.Minify | resources.Fingerprint }}
<script src="{{ $js.Permalink }}"></script>

Hugovi vlastně říkáte, že má najít zdroje právě ve zmíněné složce, tam vyhledá soubor dle jména, minifikuje jej a přidá mu ještě otisk (takové to číslo na konci URL adresy ke skriptu). Otisk se vám hodí pro vyřešení problémů s dlouhým cacheováním v prohlížeči, když mezitím soubor změníte. Má pak prostě po přegenerování webu jiný název. Na druhém řádku je už jenom vypsání cesty k souboru.

Jak vyfiltrovat několik záznamů daného typu obsahu pro zobrazení na titulce webu? Věc, kterou bych v Drupalu naklikal během chvilky s modulem Views, jsem si tu musel chvíli rozmýšlet. Mám pocit, že jsem nemohl najít správnou ukázku výběru stránek dle filtru. Ale je to snadné, jako vše v Hugo:

{{ $pages := where .Pages "Type" "katalog" }}
{{ range first 6 $pages }}
  <a href="{{ .RelPermalink }}">{{.Title}}/a>                                                                                                  
{{ end }}

Výše uvedené vypíše šest nejnovějších záznamů typu katalog.

Jak formátovat datum a čas v Hugo? Formátování času v Hugo je docela podivná věc. Nicméně vězte, že máte-li ve front matter uveden čas jako ISO8601, pak zobrazení ve formátu den. měsíc. uděláte v šabloně tímto zápisem {{ .Date.Format "2. 1." }}. Rok zase jako {{ .Date.Format "2006" }}. A ano, opravdu se tam píše 2006 ;-)

Hotový web postavený s Hugo

Generování Hugem i s minifikací a především změnami velikostí obrázků je opravdu velice rychlé. Napsat, že by složka public, kterou pak nakopíruju na server, byla vytvořena během pár sekund, je vlastně špatně. I to je moc dlouho.

Web BrnoMasáže.cz vytvořený v Hugo

Hugem jsem tedy docela snadno nahradil původní web na Drupalu. Najdete jej na adrese www.brnomasaze.cz. Zadání rychlého a na rozdíl od původního stavu i responzivního webu jsem díky šabloně splnil. Podrobněji k webu někdy příště. Nicméně ve vztahu k Hugo:

  1. Používám archetypy obsahu článek, typ masáže, katalog. K tomu neroztříděné stránky.
  2. Na titulce je několik různých výpisů těchto obsahů podle různých kritérií a řazení.
  3. Katalog masáží, typy masáží a články – to vše jsou výpisy různých typů obsahu
  4. V detailu každého záznamu v katalogu využívám shortcode k tomu, abych vygeneroval zobrazení kontaktních údajů i mapu. Příslušné hodnoty zapisuji do MD souboru do části front matter.

A to je vše. Pokud se také s Hugem potýkáte a narazili jste na nějaký problém, klidně napište do komentářů. Třeba poradím. Já určitě u tohoto generátoru webů zůstanu a pravděpodobně na něj převedu několik dalších webů, které mají historicky nějaký redakční systém, ale obsah se tam často nemění. Proč tedy trávit čas aktualizacemi něčeho, co nahradí pár vygenerovaných HTML souborů.

Tagy

Buďme ve spojení, přihlaste se k newsletteru

Odesláním formuláře souhlasíte s podmínkami zpracováním osobních údajů. 
Více informací v Ochrana osobních údajů.

Autor článku: Jan Polzer

Tvůrce webů z Brna se specializací na Drupal, WordPress a Symfony. Acquia Certified Developer & Site Builder. Autor několika knih o Drupalu.
Marketing Director v Lesensky.cz. Ve volných chvílích podnikám výlety na souši i po vodě. Více se dozvíte na polzer.cz a mém LinkedIn profilu.

Komentáře k článku

Profile picture for user Jan Polzer

Protože jsem si chtěl vyzkoušet tvorbu webu v nějakém statickém generátoru. Pico je fajn kvůli Markdown a Twig. Taky Grav je fajn. Ale cílem bylo také zbavit se nutnosti pořád nějakých aktualizací. Z Hugo mi vypadne prosté HTML.

Přidat komentář

Odesláním komentáře souhlasíte s podmínkami Ochrany osobních údajů

reklama
Moje kniha o CMS Drupal

 

Kniha 333 tipů a triků pro Drupal 9


Více na KnihyPolzer.cz

Sledujte Maxiorla na Facebooku

Maxiorel na Facebooku

Poslední komentáře
Hosting pro Drupal a WordPress

Hledáte český webhosting vhodný nejenom pro redakční systém Drupal? Tak vyzkoušejte Webhosting C4 za 1200 Kč na rok s doménou v ceně, 20 GB prostoru a automatické navyšováním o 2 GB každý rok. Podrobnosti zde.

@maxiorel na Twitteru

Maxiorel na Twitteru