forked from em/bakalarka
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
330 lines
28 KiB
TeX
330 lines
28 KiB
TeX
\chapter{Modelová implementace}\label{kap:modelova-implementace}
|
|
|
|
Tato část práce se věnuje tvorbě modelové implementace systému pro generování statického webu dle definovaných požadavků v kapitole \ref{kap:taxonomie-pozadavku}. Systém je vytvářen na základě poznatků z předchozích částí práce.
|
|
|
|
\section{Výběr vhodného systému}\label{kap:vyber-vhodneho-systemu}
|
|
|
|
Modelový web se skládá ze dvou sytstémů, a to ze systému pro správu obsahu a systému pro jeho generování do HTML.
|
|
|
|
Pro správu obsahu i šablon a statických souborů byl zvolen distribuovaný verzovací systém Git. Hlavní výhodou tohoto verzovacího systému je jeho rozšířené využití v praxi a dokáže s ním tedy pracovat spousta uživatelů. Zároveň má v porovnání s jinými verzovacími systémy spousty výhod.\todo{Příklady + citace}
|
|
|
|
Protože forma modelového webu odpovídá paradigmatu webové prezentace ze sekce \ref{kap:paradigmata-webova-prezentace}, byl pro jeho generování použit program Zola\footnote{\url{https://www.getzola.org/}}, jehož výhody jsou v sekci \ref{kap:paradigmata-webova-prezentace} popsány.
|
|
|
|
\section{Tvorba šablony}
|
|
|
|
Jak se uvádí v dokumentaci\footnote{\url{https://www.getzola.org/documentation/content/overview/}}, Zola pracuje s několika druhy stránek, primárně s takzvanou \uv{sekcí} a \uv{stránkou}. Každá sekce může mít vlastní obsah, ovšem může obsahovat i další subsekce, díky čemuž lze dělit obsah do stromové struktury. Stránka slouží pouze k předání obsahu a nikoliv k dalšímu větvení struktury. Dá se tedy říci, že stránka značí konec dané větve. Kořenem celého stromu je speciální sekce s názvem \uv{index}. Každá tato část standardně využívá vlastní HTML šablonu, ovšem nejde o pravidlo a každá část větve může využívat jinou šablonu. To je užitečné například u stránek s různým druhem obsahu. V rámci modelového webu zůstává druh obsahu stejný a není tedy třeba odchylovat se od standardní struktury.
|
|
|
|
Soubory se šablonami se nachází ve složce \texttt{templates/}, ve které generátor vždy očekává šablonu \texttt{index.html}. Ta se využívá jak k vykreslení úvodní kořenové stránky, tak ji mohou ostatní šablony rozšiřovat. Tato kořenová šablona tedy obsahuje základní strukturu celé stránky, přičemž navazující šablony jen mění určité části obsahu a nedefinují celou strukturu znovu.
|
|
|
|
Generátor v šablonách hledá vlastní řídící sekvence, které se popisují závorkami. Existují tři druhy kombinací, které lze použít:
|
|
|
|
\begin{itemize}
|
|
\item \texttt{\{\% \%\}} -- Metoda, funkce, cykly, podmínky, práce s proměnnou atd.
|
|
\item \texttt{\{\{ \}\}} -- Výpis do HTML
|
|
\item \texttt{\{\# \#\}} -- Komentář
|
|
\end{itemize}
|
|
|
|
Generátor také vyžaduje konfigurační soubor \texttt{config.toml} v kořenové složce projektu, který obsahuje různé nastavení stránky, globální proměnné a chování generátoru.
|
|
|
|
\begin{lstlisting}[label=lst:jednoducha-konfigurace,caption=Příklad jednoduché konfigurace v souboru \texttt{config.toml}]
|
|
# Adresa ze které se generují odkazy
|
|
base_url = "https://ucitelonline.pedf.cuni.cz"
|
|
# Název stránky
|
|
title = "Učitel online"
|
|
# Popis stránky
|
|
description = "Web pro ditstribuci užitečných materiálů"
|
|
# Zda se bude zpracovávat CSS systémem Sass
|
|
compile_sass = true
|
|
\end{lstlisting}
|
|
|
|
\todo[inline]{Tohle je pěkná ukázka, vyberte klidně ještě jednu dvě, které jsou něčím zajímavé, typické, nebo naopak výjimečné pro ilustraci toho, co chcete o daném, systému sdělit.}
|
|
|
|
Systém vždy zpracuje úvodní šablonu \texttt{index.html}, ze které pak lze odvíjet ostatní šablony. Tato hlavní šablona obsahuje strukturu celé webové stránky a nesmí v ní tedy chybět validní HTML struktura, tedy hlavička, tělo, metadata, kódování a podobně. Do struktury lze vkládat libovolné řídící sekvence pro generátor, které ovlivňují výsledný výstup.
|
|
|
|
\begin{lstlisting}[label=lst:zakladni-sablona,caption=Základní šablona \texttt{index.html}]
|
|
<!DOCTYPE html>
|
|
<html lang="cs">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>{{ config.title }}</title>
|
|
</head>
|
|
<body>
|
|
</body>
|
|
</html>
|
|
\end{lstlisting}
|
|
|
|
V příkladu \ref{lst:zakladni-sablona} je název stránky mezi tagy \texttt{<title></title>} vyplněn generátorem. Ten do šablony vloží hodnotu konstanty \texttt{config.title}, která je nastavena v konfiguračním souboru \texttt{config.toml} z příkladu \ref{lst:jednoducha-konfigurace}. Názvem stránky bude tedy řetězec \uv{Učitel online}. Generátor dokáže převzít kteroukoliv konstantu z kontextu konfiguračního souboru.
|
|
|
|
Všechny direktivy lze v rámci generátoru navazovat na sebe, podobně jako je tomu v Unixových systémech. Spojování funkcí a filtrů se provádí znakem \texttt{|}, stejně jako v POSIX\footnote{Portable Operating System Interface -- Rodina standardů Unixových systémů} shellu, kde výstup jednoho příkazu se stane vstupem příkazu navazujícího. Například je možné název stránky vypsat ve velkých písmenech i přesto, že v konfiguračním souboru je formátován pouze s velkým písmenem na začátku. K převedení na velká písmena slouží filtr \texttt{upper}. Názvem stránky bude po zpracování programem \ref{lst:filtr-upper} řetězec \uv{UČITEL ONLINE}.
|
|
|
|
\begin{lstlisting}[label=lst:filtr-upper,caption=Základní šablona s filtrem pro přepsání názvu na velká písmena]
|
|
<!DOCTYPE html>
|
|
<html lang="cs">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>{{ config.title | upper }}</title>
|
|
</head>
|
|
<body>
|
|
</body>
|
|
</html>
|
|
\end{lstlisting}
|
|
|
|
V šabloně je také možnost vytvořit bloky, které lze v navazujících šablonách měnit. K vysvětlení principu fungování bloků je možné název stránky z příkladu \ref{lst:filtr-upper} obalit blokem \texttt{title} a těla vložit blok \texttt{content}.
|
|
|
|
\begin{lstlisting}[label=lst:bloky,caption=Využití bloků v šabloně z příkladu \ref{lst:filtr-upper}]
|
|
<!DOCTYPE html>
|
|
<html lang="cs">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>{% block title %}{{ config.title | upper }}{% endblock %}</title>
|
|
</head>
|
|
<body>
|
|
{% block content %}
|
|
Ahoj, světe!
|
|
{% endblock %}
|
|
</body>
|
|
</html>
|
|
\end{lstlisting}
|
|
|
|
Název stránky zůstane stejný a v jejím těle přibude text \uv{Ahoj, světe!}. Vytvoříme-li novou šablonu s názvem \texttt{section.html}, generátor nám umožní rozšířit ji o původní šablonu \texttt{index.html} a měnit pouze definované bloky. Není tedy nutné znovu definovat celou strukturu stránky. Pro importování, nebo-li rozšíření šablony, slouží direktiva \texttt{extends}.
|
|
|
|
\begin{lstlisting}[label=lst:sablona-section,caption=Definice nové šablony \texttt{section.html} rozšiřující šablonu z příkladu \ref{lst:bloky}]
|
|
{% extends "index.html" %}
|
|
{% block title %}{{ config.title | upper }} – {{ section.title }}{% endblock %}
|
|
{% block content %}
|
|
Toto je obsah kategorie.
|
|
{% endblock %}
|
|
\end{lstlisting}
|
|
|
|
Šablona \texttt{section.html} se v rámci generátoru Zola implicitně využívá pro všechny existující sekce\footnote{\url{https://www.getzola.org/documentation/content/section/}}. Názvem stránky v této šabloně bude, stejně jako u hlavní šablony, název stránky z konstanty \texttt{config.title} definované v konfiguračním souboru, ale také spojovník a název dané sekce. Za pseudo-výstup lze považovat například \uv{UČITEL ONLINE -- základní a střední škola}, bude-li se uživatel nacházet v sekci pro základní a střední školy.
|
|
|
|
V bloku s obsahem bude původní obsah \uv{Ahoj, světe!} nahrazen za řetězec \uv{Toto je obsah kategorie}. Ten ovšem nechceme definovat přímo v šabloně, nýbrž cílem generátoru je vyplňovat obsah ze zdrojových souborů v sázecím jazyce, viz. sekce \ref{kap:princip-generatoru}. Zola pro vkládání obsahu využívá stejný princip jako v ostatních případech, tedy vypsání obsahu proměnné, v tomto případě proměnné \texttt{section.content}, která obsahuje zkompilované HTML z daného Markdown souboru. Zároveň je dobrou praktikou provést vyčištění vstupu filtrem \texttt{safe}\footnote{\url{https://tera.netlify.com/docs/\#safe}}.
|
|
|
|
|
|
\begin{lstlisting}[label=lst:sablona-section-vlozeni-obsahu,caption=Vkládání obsahu ze zdrojového Markdown souboru]
|
|
{% extends "index.html" %}
|
|
{% block title %}{{ config.title | upper }} – {{ section.title }}{% endblock %}
|
|
{% block content %}
|
|
{{ section.content | safe }}
|
|
{% endblock %}
|
|
\end{lstlisting}
|
|
|
|
Z principu by žádný obsah neměl být definován přímo v šabloně, nýbrž by měl být do stránky vkládán generátorem z proměnných, nebo ze sázeného obsahu. V rámci modelové implementace je toto nepsané pravidlo dodržováno.
|
|
|
|
\section{Automatické generování vícevrstvé navigace}
|
|
|
|
\quest[inline]{Je následující část srozumitelná?}
|
|
|
|
Obsah modelové implementace je dělen do stromové datové struktury o potencionálně nekonečné hloubce, kdy každá část větve je v rámci generátoru vlastní kategorií, nikoliv stránkou. Pro modelovou implementaci bylo zvoleno, aby navigace byla generována v návaznosti na aktivní cestu ve stromě. Ve stránce jsou dvě různé navigace, jedna hlavní a vždy vidiětelná, která obsahuje rozdělení obsahu dle škol a druhá navigace, která zobrazuje aktivní větev stromu.
|
|
|
|
První vrstvou struktury jsou hlavní sekce, v rámci implementace pojemnované jako $L_1$, které jsou vypsány vždy ve vlastní navigaci. Pod touto navigací se zobrazuje seznam všech kategorií, které vybraná položka v $L_1$ obsahuje. Pokud uživatel zvolí kteroukoliv položku v $L_2$, v navigaci se objeví další sloupec, který obsahuje všechny podkategorie vybrané položky, tedy položky ve vrstvě $L_3$. Takto lze stromem procházet potencionálně do nekonečna. Styly modelové šablony ovšem počítají s maximální hloubkou čtyř subkategorií.
|
|
|
|
Tato funkcionalita je implementována pomocí dvou cyklů. První cyklus (příklad \ref{lst:obsah-cyklus1}) se provádí pro všechny rodiče aktivní ktegorie vrstev $L_2,L_3,\dotsc,L_n$, kde $n$ je aktuílní vrstva. V každé iteraci se mění kontext, ve kterém generátor pracuje. Z daného kontextu generátor vypisuje všechny subkategorie každého svého rodiče. V druhém cyklu (příklad \ref{lst:obsah-cyklus2}) se vypisují všichni potomci dané stránky, tedy potomci ve vrstvě $L_{n+1}$.
|
|
|
|
\begin{lstlisting}[label=lst:obsah-cyklus1,caption=Cyklus pro vypisování všech rodičů v dané větvi navigace]
|
|
{% if section.ancestors %}
|
|
{% for s in section.ancestors %}
|
|
{% if loop.index < 2 %}{% continue %}{% endif %}
|
|
<ul>
|
|
{% set s = get_section(path=s) %}
|
|
{% for s in s.subsections %}
|
|
{% set s = get_section(path=s) %}
|
|
<li><a href="{{ s.permalink }}"
|
|
{% if current_path == s.path %}
|
|
class="active"
|
|
{% elif current_path is containing(s.path) %}
|
|
class="ancestor"
|
|
{% endif %}
|
|
>{{ s.title }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endfor %}
|
|
{% endif %}
|
|
\end{lstlisting}
|
|
|
|
\begin{lstlisting}[label=lst:obsah-cyklus2,caption=Cyklus pro vypisování všech potomků dané stránky do navigace]
|
|
{% if section.subsections %}
|
|
<ul>
|
|
{% for s in section.subsections %}
|
|
{% set s = get_section(path=s) %}
|
|
<li><a href="{{ s.permalink }}">{{ s.title }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
\end{lstlisting}
|
|
|
|
\section{Rozšíření šablony}
|
|
|
|
Ve výchozím stavu generátor neumí vkládat nic jiného, než je uvedeno ve specifikaci CommonMark, viz. sekce \ref{kap:markdown}. Dle požadavků modelového webu je nutné, aby generátor uměl vkládat videa přímo do stránky. Taková funkcionalita není soušástí specifikace CommonMark a je tedy potřeba rozšířit generátor. Nejvhodnějším způsobem přidání vlastních funkcionalit je využití filtrů, které se v rámci generátoru nazývají \uv{shortcode}.
|
|
|
|
Principem vlastních filtrů je to, že si uživatel vytvoří vlastní šablonu, kterou lze vyvolat speciální řídící sekvencí přímo z obsahu. Každý tento shortcode může pracovat s libovolným množstvím proměnných a po zpracování vloží do místa vyvolání zkompilovaný HTML kód. Lze tedy tvrdit, že shortcode je v své podstatě imperativní funkce, která umí pracovat s parametry.
|
|
|
|
Pro tvorbu těchto filtrů je v generátoru Zola určena složka \texttt{templates/shortcodes}, která obsahuje jejich HTML šablony a kód pro zpracování generátorem. Název HTML souboru definuje název vlastního filtru. Vytvoříme-li uvitř této složky soubor nazvaný \texttt{video.html}, budeme v obsahu schopni využívat vlastní filtr s názvem \texttt{video}.
|
|
|
|
\begin{lstlisting}[label=lst:jednoduchy-filtr,caption=Příklad jednoduchého filtru s jedním atributem]
|
|
<video controls><source src="{{ src }}"></video>
|
|
\end{lstlisting}
|
|
|
|
V příkladu \ref{lst:jednoduchy-filtr} bude filtr očekávat atribut \texttt{src} a bude vracet jednoduchý HTML kód pro vložení videa do stránky. Tento filtr lze vyvolat kdekoliv v obsahu, tedy v kterémkoliv souboru s koncovkou \texttt{.md}. Za názvem filtru se do závorky uvádí parametry oddělené čárkou. U posledního parametru se čárky nevuvádí, což platí i v případě, kdy se uvádí pouze jeden parametr, jako je tomu v příkladu \ref{lst:vyvolani-filtru}.
|
|
|
|
\begin{lstlisting}[label=lst:vyvolani-filtru,caption=Vyvolání vlastního filtru s jedním parametrem]
|
|
{{ video(src="video.webm") }}
|
|
\end{lstlisting}
|
|
|
|
V rámci vybraného generátoru není nutné specifikovat atributy na jeden řádek a lze je pro přehlednost vypisovat na více řádků, jako tomu je například u programu \ref{lst:formatovani-atributu}, zůstane-li dodržena koncepce oddělení atributů čárkou, tedy že poslední atribut vždy zůstane bez čárky. Výstupem této direktivy bude následující HTML kód.
|
|
|
|
\begin{lstlisting}[caption=Výstup direktivy z příkladu \ref{lst:jednoduchy-filtr}]
|
|
<video controls><source src="video.webm"></video>
|
|
\end{lstlisting}
|
|
|
|
Součástí požadavků pro modelový web jsou i citace přiložených souborů a videí. Existující filtr je tedy třeba rozšířit o možnost přiložení různých metadat. Tato metadata ovšem nejsou pro vložení videa povinná. Ve specifikaci vlastních filtrů lze využívat všechny operátory, které generátor nabízí. Nejlepším přístupem k tomuto problému je tedy využití jednoduchých podmínek, které kontrolují, zda je každá z hodnot zadána jako parametr a v případě že ano, vepíše se do obsahu. Atributy ošetřené podmínkami tedy nejsou povinné, zatímco nevyplněný atribut \texttt{src} by při generování vyvolal chybu. V následujícím příkladu jsou přidány podmínky pro kontrolu a případné vložení, jimiž jsou název videa (\texttt{title}), jméno autora (\texttt{author}) a rok vytvoření (\texttt{year}).
|
|
|
|
\begin{lstlisting}[label=lst:filtr-s-podminkami,caption=Filtr pro vkládání videa s využitím podmínek]
|
|
<video controls><source src="{{ src }}"></video>
|
|
{% if title or year and author %}
|
|
<div class="metadata">
|
|
{% if title %}{{ title }}{% endif %}
|
|
{% if author and year %}
|
|
({{ year }}, {{ author }})
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
\end{lstlisting}
|
|
|
|
Filtr je možné opět vyvolat pomocí stejné direktivy kdekoliv v obsahu, ovšem nyní lze libovolně přidat parametry pro metadata.
|
|
|
|
\begin{lstlisting}[label=lst:formatovani-atributu,caption=Vyvolání filtru \ref{lst:filtr-s-podminkami} s formátováním na řádky]
|
|
{{ video(
|
|
src="video.webm",
|
|
title="Název videa",
|
|
author="Jméno autora",
|
|
year="2020"
|
|
) }}
|
|
\end{lstlisting}
|
|
|
|
Protože byly zadány všechny povinné i nepovinné atributy, výtupem toho filtru budou i části kódu s metadaty.
|
|
|
|
\begin{lstlisting}[caption=Výstup direktivy z příkladu \ref{lst:formatovani-atributu}]
|
|
<video controls><source src="video.webm"></video>
|
|
<div class="metadata">
|
|
Název videa (2020, Jméno autora)
|
|
</div>
|
|
\end{lstlisting}
|
|
|
|
Pro modelový web byla zvážena možnost vypisování obsahu automaticky, tedy že program zkontroluje složku s obsahem a pokud narazí na soubor se specifikovanou koncovkou, vypíše jej do obsahu podle daných pravidel. Generátor Zola umožňuje prohledávání složek a práci se soubory, v rámci Zoly takzvanými \uv{assety}. Tuto funkcionalitu lze tedy implementovat jednoduchým cyklem a filtem, které zpracují všechny případné soubory ve složce dané stránky. Zoubory lze filtrovat mnoha způsoby, z nichž je nejuniverzálnější funkce \texttt{matching()}, která dovoluje filtrovat vstup regulárními výrazy dle implementace regex v jazyce Rust\footnote{\url{https://docs.rs/regex/1.3.6/regex/}}. V následujícím příkladu je pro ilustraci této funkcionality implementován program vypisující obrázky s předem definovanými koncovkami.
|
|
|
|
\begin{lstlisting}[caption=Automatický výpis obrázků s pevně definovanými koncovkami]
|
|
{% if section.assets %}
|
|
{% for asset in section.assets %}
|
|
{% if asset is matching("\.(?i:jpg|gif|png)$") %}
|
|
<img src="{{ get_url(path=asset) }}" alt="{{ asset }}">
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
\end{lstlisting}
|
|
|
|
Toto řešení ovšem není ve výsledném modelu implemntováno, protože jedním z požadavků je možnost vkládání souborů na libovolné místo v obsahu. Na stejném principu je ovšem vytvořen filtr pro vládání souborů, který tento požadavek splňuje. Výhodou filtru je, že ho lze vyvolat kdekoliv v obsahu a není vázán na pevně dané místo v šabloně. Ten očekává alespoň jeden parametr uvádějící název souboru bez koncovky, pro dle kterého pak filtr vyhledá všechny různé formáty s tímto názvem a ty vloží do stránky. Druhým libovolným parametrem je název souboru, který se do stránky vloží místo názvu souboru. to umožňuje uivateli volně pracovat s názvy souborů v souborvé struktuře bez ovlivnění obsahu stránky.
|
|
|
|
\begin{lstlisting}[label=lst:filtr-souboru,caption=Filtr pro výpis souborů s automatickým hledáním]
|
|
{% if section.assets and filename %}
|
|
<div class="file">
|
|
<div class="title">
|
|
{% if title %}
|
|
{{ title }}
|
|
{% else %}
|
|
{{ filename }}
|
|
{% endif %}
|
|
</div>
|
|
{% for asset in section.assets %}
|
|
{% if asset is matching(section.path ~ filename ~ "\..*$") %}
|
|
<a href="{{ get_url(path=asset) }}" class="format">{{ asset | split(pat=".") | last }}</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
\end{lstlisting}
|
|
|
|
V první části filtr zkontroluje, zda byl vyplněn parametr \texttt{title} a v přípdě že ano, nastaví ho jako název souoru v obsahu. V opačném případě využije název souboru samotného. Ve druhém kroku nastává kontrola, zda se ve složce nacházejí soubory (mimo hlavní soubor \texttt{\_index.md}) a pokud ano, přes všechny soubory se iteruje kontrola, zda soubor splňuje podmínku názvu. Kontrola této podmínky je tvořena kombinací proměnných generátoru a regulárního výrazu. Každý soubor který splňuje podmínku je poté vypsán do obahu jako přímý odkaz k jeho stažení.
|
|
|
|
Jako text v odkazu se použije koncovka souboru, která se záskává spojením několika filtrů, tedy filtru \texttt{split(pat=".")}, který rozdělí řetězec podle znaku tečka do pole a navazující filtr \texttt{last} vrátí poslední položku v poli. Tím filtr získá samotnou koncovku souboru.
|
|
|
|
Filtr lze vyvolat stejně, jako je tomu u filtru pro vkládání videa. Název filtru je opět definován názvem souboru \texttt{tmeplates/shortcodes/document.html} a bude jím tedy název \texttt{document()}.
|
|
|
|
\begin{lstlisting}[label=lst:vyvolani-filtru-souboru,caption=Vyvolání filtru \ref{lst:filtr-souboru}]
|
|
{{ document(
|
|
filename="pracovni-list",
|
|
title="Pracovní list"
|
|
) }}
|
|
\end{lstlisting}
|
|
|
|
V příkladu \ref{lst:vyvolani-filtru-souboru} je definován i nepovinný atribut \texttt{title}, který kvůli přehlednosti umožňuje nastavit název. Atribut \texttt{filename} definuje název souboru ve složce bez koncovky. Všechny soubory, které chce uživatel vypsat, musí tedy mít stejný název a musí se lišit pouze koncovkou. Jsou li ve složce soubory s názvem \texttt{pracovni-list} a koncovkami \texttt{pdf}, \texttt{odt}, \texttt{djvu} a \texttt{ps}, bute výstupem filtru následující HTML.
|
|
|
|
\begin{lstlisting}[caption=Výstup direktivy z příkladu \ref{lst:vyvolani-filtru-souboru}]
|
|
<div class="file">
|
|
<div class="title">Pracovní list</div>
|
|
<a href="pracovni-list.pdf">pdf</a>
|
|
<a href="pracovni-list.odt">odt</a>
|
|
<a href="pracovni-list.djvu">djvu</a>
|
|
<a href="pracovni-list.ps">ps</a>
|
|
</div>
|
|
\end{lstlisting}
|
|
|
|
\section{Optimalizace}\label{kap:optimalizace}
|
|
|
|
Optimalizace modelové implementace je provedena na základě článku ze serveru \cite{calomel_optimization}, který se věnuje sestavením užitečných rad pro optimalizaci webových stránek na serverech s omezeným připojením do sítě a pro zvýšení spokojenosti uživatelů z užívání optimalizovaného webu, jak je rozebráno v sekci \ref{kap:vyhody-statickych-webovych-stranek}.
|
|
|
|
Jak se na webu Colomel píše, provozování webserveru může být hodnotná zkušenost, ale zároveň může být i zkouškou trpělivosti. Chcete svým uživatelům předávat všechny vaše stránky a obrázky, ovšem máte jen omezenou šířku pásma, pomocí které můžete data přenášet. Pokud přetížíte své pipojení, klienti nevštěvující váš web server si budou myslet, že je pomalý a neresponzivní. Je tedy třeba webový server nastavit tím nejlepším možným způsobem s cílem získat co nejvíce návštěv a zlepšit zážitek vašim návštěvníkům. Následující rady slouží ke snížení zátěže serveru, ke zrcyhlení odesílání stránek a k zastavení nechtěnného a škodlivého provozu.
|
|
|
|
Práce se věnuje pouze technickým optimalizacím spojených s tvorbou samotné webové stránky, nikoliv však optimalizacím sítě, web serveru a vizuálního návrhu. Nenačítá-li se stránka během několika vteřin, většina uživatelů jednoduše odejde. Cílem této sekce je provést optimalizace, které urychlí načítání modelové implementace.
|
|
|
|
\subsection{Typy a kvalita obrázků}
|
|
|
|
Fotografie a grafika využívají mnohem více dat pro přenos než běžný HTML text a je tedy nutné provést optimalizaci (kompresi) obrázků na co nejmenší možnou velikost souborů. Obrázky není třeba renderovat na více než 72 dpi a pro každý druh grafiky je třeba zvolit vhodný tofmát, tj. formát JPEG pro fotografie a formáty PNG či SVG pro jednoduchou grafiku. Rastrové obrázky mají pouze potřebné rozlišení, tedy maximálně hodnotu největšího rozlišení, které se ve stránce bude zobrazovat. Klíčové je také nevyužívat obrázky v případě, kde je lze nahradit čístým HTML a CSS.
|
|
|
|
Obrázky ve formátu JPEG mají velice efektivní ztrátovou kompresi, pomocí které lze zredukovat velikost obrázku o značnou část. Autor článku tvrdí, že většinu obrázků lze komprimovat až o 50\% bez viditelné ztráty na kvalitě. Své obrázky dokonce zkomprimoval ze 27 kilobajtů na pouhých 8 kilobajtů s JPEG kompresí 60\%.
|
|
|
|
\subsection{Ikona \textit{favicon.ico}}
|
|
|
|
Původně je \textit{favicon.ico} výtvorem firmy Microsoft, kdy její Internet Explorer automaticky odesílal požadavek na pevnou URL \texttt{/favicon.ico} od kořene webového serveru. Jde o malou ikonku, která se dnes zobrazuje u každé záložky s webovou stránkou. Problémem je to, že se požadavkům o ní nelze vyhnout a vždy se počítá s tím, že ikona na web serveru existuje. Odesílá se vždy s každou stránkou a některé prohlížeče se po ní dotazují z neznámých důvodu dvakrát. Autor článku uvádí, že u některých serverů bylo až 30\% přenesených dat využito jen na servírování ikony.
|
|
|
|
Principem optimalizace je udržet ikonu ji co nejmenší, v nejlepším případě tak malou, že se vejde do jednoho TCP paketu, tedy do velikosti 1460 bajtů na většině systémů. Toho lze docílit tím, že ikona nebude větší než 16x16 pixelů s nízkou barevnou hloubkou, nejlépe s pouze čtyřmi barvami. Také je možné poslat pouze 1x1 pixelů veliký prázdný obrázek, nebo vracet stavový kód 204\footnote{204 No Content -- Server úspěšně zpracoval požadavek, ale nevrací žádný obsah.} a neodesílat ikonu žádnou.
|
|
|
|
\subsection{Obecné HTML optimalizace}
|
|
|
|
Redukcí nepotřebných znaků v HTML lze také ušetřit značnou část přenosu dat. Dobrými praktikami mohou být:
|
|
|
|
\begin{itemize}
|
|
\item nepoužívání HTML komentářů,
|
|
\item využití CSS pro formátování stránek,
|
|
\item využití oddělovače nebo elementu \texttt{span} namísto tabulek,
|
|
\item odstranění přebytečných tagů a prázdných mezer a řádků,
|
|
\item vytvoření obrázkových náhledů namísto odesílání obrázků v plném rozlišení,
|
|
\item recyklování již použitých obrázků a tlačítek.
|
|
\end{itemize}
|
|
|
|
K odstranění přebytečných mezer, zalomení řádků, HTML komentářů a prázdných řádků lze použít automatický filtr, který provede kompresi výstupu. \todo{Přesunout do návrhu pro rozšíření?}Generátor Zola provádí kompresi CSS, ovšem nemá zabudovanou funkcionalitu pro minifikaci výsledného HTML, která je ovšem v době psaní této práce vyvíjena\footnote{\url{https://github.com/getzola/zola/issues/542}}.
|
|
|
|
Touto redukcí lze ušetřit 2\% přenosu dat oproti ručně psanému neoptimalizovanému kódu. Je-li průměrná velikost stránky sto kilobajtů, lze touto optimalizací ušetřit dva kilobajty při každém odeslání stránky. Při odeslání sta tisíce stránek za měsíc je ve výsledku ušetřeno dvě stě megabajtů dat, které jsou jinak zbytečně odesílány uživatelům, kteří je stejně nezobrazí.
|
|
|
|
Další obecné rady pro optimalizaci HTML jsou uvedeny na serveru \cite{yahoo_optimization}, kde se uvádí spousta dalších způsobů ke zrychlení načítání stránky a k nižšímu vytížení sítě.
|
|
|
|
Připojením externích CSS a JavaScript souborů je umožněno jejich ukládání do paměti cache, což snižuje HTTP požadavky vůči serveru. Je-li obsah těchto souborů přímo ve stránce, je odesílán pokaždé s novou stránkou a to vede ke zbytečnému vytěžování sítě. S tím souvísí i velikost stránek, kdy soubory větší než je daná maximální velikost se do paměti cache neukládají a je proto dobré tuto velikost nepřekračovat.
|
|
|
|
\quest[inline]{U starých zařízení jsou pevně dané velikosti, například v roce 2011 byly limity 25.6K u iOS nebo 5M u Firefoxu. Mám je zde uvádět, i když se to rychle mění, nebo to stačí takhle obecně?}
|
|
|
|
Připojením externího CSS přímo do hlavičky je umožněno progresivní vykreslování webové stránky, které urychluje \uv{Time To First Byte}, viz sekce \ref{kap:vyhody-statickych-webovych-stranek}. Naopak umístěním případných JavaScript souborů až na konec celé stránky se prioritizuje načítání viditelného obsahu před méně důležitými skripty.
|
|
|
|
Je také důležité udržovat validní HTML, kdy například chybějící atribut \texttt{src=""} způsobuje odesílání nevyžádaných požadavků na server.
|
|
|
|
\quest[inline]{HTML5 už specifikuje, aby prohlížeče kvůli prázdnému \textit{src} neposílaly další požadavaek. Je tedy nutné uvádět tento příklad?}
|
|
|
|
\subsection{Videa a jejich vložení do stránky}
|
|
|
|
\todo[inline]{Výhody CDN a problematika sledování uživatelů.}
|
|
|
|
\section{Správa obsahu a verzování}
|
|
|
|
Statické stránky neumožňují správu uživatelů v prámci webové aplikace, tedy že se případný editor nebo administrátor přihlásí a upravuje obsah klikáním, či psaním ve WYSIWYG\footnote{What You See Is What You Get -- Princip editoru který během psaní formátuje text tak, jak bude ve výsledku vypadat, například LibreOffice Writer atd.} editoru. Správu uživatelů lze jednoduše řešit omezením přístupu na web server, kde jen oprávnění uživatelé mohou do obsahu zasahovat. To je ovšem velmi tězkopádné řešení, protože neumožňuje práci více uživatelům najednou a neudržuje předešlé verze obsahu a historii úprav. Lepší alternativou je využití některého verzovacího systému. Pro účely modelové implementace byl vybrán distribuovaný verzovací systém Git, jak je vysvětleno v sekci \ref{kap:vyber-vhodneho-systemu}.
|
|
|
|
|