HTML stránka může obsahovat celou řadu tagů a odkazů, které pomohou buď prohlížečům nebo vyhledávačům lépe pochopit rozložení stránek a rychleji ho načíst a zobrazit.
Pokud například načítáte obrázky a soubory z CDN, můžete prohlížeči říct, že se má připravit a najít nejbližší CDN server ještě před tím, než začnete soubory stahovat. Pokud máte seznam nebo článek rozdělený na stránky, můžete označit odkaz na následující stránku a prohlížeč pak tuto stránku načte ještě dříve, než ji bude chtít uživatel zobrazit; vyhledávač naopak díky tomu spojí všechny položky na jednu stránku a nebude uživatele odkazovat doprostřed seznamu.
Canonical
První označení slouží k tomu, abyste vyhledávačům řekli, že vaše stránka ve skutečnosti obsahuje stejný nebo upravený obsah z jiné stránky.
To může být např. seznam, který je seřazený buď podle data vytvoření nebo podle oblíbenosti, nebo stránka doplňující informace, jako je třeba limitovaná edice výrobku, který má ale stejný popis jako základní edice.
Informaci vložíte do HTML hlavičky pomocí tagu:
<!-- stránka oblibene.html je jinak serazene vsechny.html -->
<html><head>
<link rel="canonical" href="vsechny.html" />
</head>...
<!-- stránky search.php?page=X obsahují skoro to samé -->
<html><head>
<link rel="canonical" href="search.php" />
</head>...
V prvním příkladu říkáme vyhledávači, že vše, co najde na stránce (oblibene.html
) je stejné nebo podobné jako stránka vsechny.html
. Vyhledávač pak veškeré poznatky o této stránce ve skutečnosti uloží tak, jako by je našel na stránce vsechny.html
.
V druhém případě pomáháme vyhledávači pochopit výsledky hledání tak, že všechny přesměrujeme na společnou stránku search.php
. Vyhledávač pak bude všechny uživatele odkazovat na základní stránku hledání, místo aby je posílal přímo na konkrétní stránku (která už nemusí být správná, protože se výsledky změnily).
Adresa může být jak relativní vůči současné stránce (jak je uvedeno v příkladech), tak i absolutní (začíná lomítkem a je absolutní vzhledem k základní adrese) a nebo dokonce i může obsahovat jméno jiné domény (např. stránka http://mujserver.cz/en/
může odkazovat na http://myserver.com/
, protože obě obsahují stejnou anglickou verzi).
Absolutní adresa se vztahuje buď k rootu serveru, nebo k základní base
adrese:
<html><head>
<base href="/clanky/">
<link rel="canonical" href="/vsechny.html" />
<!-- odkazuje na: http:/mujserver.cz/clanky/vsechny.html -->
</head>
Účel kanonického přesměrování je samozřejmě v tom, získat co nejlepší hodnocení. Vyhledávače totiž často považují duplicitní obsah za přitěžující (uživatel se nedozví nic nového) a tímto určíme, která stránka je ta původní a má získat „všechny body“. Naopak rozdílný obsah na podobných stránkách roztříští návštěvnost a oblibu webu mezi jednotlivé podstránky a my můžeme určit, že se všechny „získané body mají sečíst“.
Obráceně, pokud kanonická stránka chce odkázat na další stránky se stejným obsahem, může to provést pomocí alternate
odkazů:
<link rel="alternate" href="/clanky/123.html">
<link rel="alternate" href="/article/123.html">
Alternativních odkazů může být ve stránce, kolik je potřeba.
Zkrácená adresa
Další typ je podobný canonical
, ale zatímco ten jednoduše odkazuje na stránku se stejným obsahem, odkaz shortlink
obsahuje URL, která by měla být 1. kratší a 2. by se neměla měnit v čase.
Zkrácená adresa by neměla obsahovat odkaz přes službu typu tinyurl nebo bit.ly, ale naopak uvádět zkrácenou adresu, kterou je schopen poskytnout sám server.
Např. pokud je adresa článku http://publishing.company.com/blog/articles/2016/what-plan-for-this-year-12345678
, může jeho zkrácená verze být třeba http://company.com/12345678
nebo http://company.com/2016-plans
. Důležité ale je, že pokud se původní adresa změní třeba na http://english.publishing.company.com/...
nebo se po několika letech článek přesune do .../blog/archive/2016/...
, měla by zkrácená adresa zůstat stejná.
To ale znamená, že systém zkrácení je potřeba dobře promyslet a počítat s tím, že všechny zkrácené adresy musí být unikátní. Na jednu stranu číselný nebo písmenný kód je snadno unikátní, protože ho budete jednoduše generovat, ale zase na první pohled nebude poznat, o co jde; kdo asi tuší, že zkrácená adresa https://youtu.be/jeBP-BFhkbM odkazuje na nové vlastnosti Chrome 50. Na druhou stranu ručně psané odkazy jsou snadno čitelné a sami o sobě přitáhnou zákazníky, jako třeba http://eshop.eu/mobil-za-pet-stovek
, ale může to dojít tak daleko, že adresa bude http://eshop.cz/nevime-co-sem-napsat
(což už se jednomu českému eshopu skutečně stalo).
Součástí samozřejmě může být i alternativní kratší adresa serveru, která se použije pro zkrácené odkazy. Např. pokud je základní adresa http://drevene-a-umelohmotne-modni-pantofle.cz/, může zkrácená adresa být http://dump.cz/
(= smetiště – i tady je ale potřeba se zamyslet!).
Zkrácené adresy jsou hlavně určeny pro služby jako Facebook, Twitter nebo WordPress, které používají krátké URL pro zkrácení odkazované zprávy a tedy úsporu místa jak na (mobilním) displeji tak i v databázi.
Zkrácenou adresu je možno uvést v HTML jako tag:
<link rel="shortlink"
href="http://company.com/2016-plans">
nebo v HTTP hlavičce (která se dá snadněji najít):
Link: <http://company.com/2016-plans>; rel=shortlink
Pokud uživatel na Facebook nebo Twitter zadá dlouhou URL, server se před zveřejněním na danou adresu podívá a pokud v HTTP nebo HTML hlavičce najde shortlink
, použije ho místo uživatelem zadané adresy.
Předchozí a další stránka
S kanonickým přesměrováním souvisí další dva odkazy, které může použít na stránce, která je z nějakého důvodu rozdělena a její obsah není dostupný najednou. Zpravidla jde o stránkované výsledky nějakého dotazu, ale může jít třeba i o článek, který je kvůli své délce rozdělen na více stránek.
V takovém případě můžeme prohlížeči a vyhledávačům poradit, který odkaz vede na další a předchozí stránku. Vyhledávače pak díky tomu mohou obsah všech stránek spojit a zahrnout do výsledků jen pod první stránku (kterou poznají podle toho, že neodkazuje na žádnou předcházející) a prohlížeč naopak může dopředu načíst další stránku v případě, že uživatel již strávil dostatek času na současné stránce, protože ho (pravděpodobně) zaujala, a je velká šance, že bude pokračovat i na další. V Modern (Metro) verzi Internet Explorer 10 a 11 na Windows 8/8.1 můžete po zapnutí Flip ahead používat swipování do stran pro procházení stránek definovaných pomocí prev
a next
odkazů.
<html><head>
<link rel="prev" href="/clanek.php?id=123&page=1" />
<link rel="next" href="/clanek.php?id=123&page=3" />
<title>Článek 123, strana 2</title>
</head>...
Další a předchozí stránku označíte odkazy prev
a next
, ve kterých uvedete adresy souvisejících stránek. První a poslední stranu samozřejmě označíte tak, že odkaz pro předchozí nebo následující stránku neuvedete.
Stejně jako canonical
mohou obsahovat relativní nebo absolutní cestu. Jen asi v případě stránkování nedává moc smysl odkazovat na jiný server, protože seznam nebo článek by měl mít pokračování na tom samém serveru; ale zakázané to není.
Odkazy next
a prev
je samozřejmě možno (a doporučeno) kombinovat s canonical
. Např. stránkovaný seznam výrobků může odkazovat na další a předchozí stránku seznamu a zároveň na stránku se všemi výrobky. Stejně tak článek rozdělený na stránky může označit další stránku textu a zároveň odkázat na verzi pro tisk, která obsahuje celý článek.
Pozor na to, že prev
a next
odkazy označují stránky se souvisejícím obsahem! Neměli by sloužit k označení dalšího článku, nebo předchozí stránky v historii. Pokud chcete ve stránce označit, že uživatel pravděpodobně bude pokračovat ve čtení dalšího souvisejícího článku, nebo že se naopak vrátí na seznam článků, použijte k tomu odkazy prefetch
a prerender
. V opačném případě byste mohli přijít o „body“ kvůli tomu, že vyhledávač nezjistí, jaké množství článku nebo výrobků na stránkách nabízíte (protože všechny výsledky započte pouze pod jedinou stránku).
Syndikace a Pingback
Další dva typy odkazů jsou určeny hlavně pro blogy a podobné služby, které mohou těmito odkazy propojovat související články.
Mějme příklad, kdy server https://blog.mozilla.org/ převezme článek o nové navrhované vlastnosti prohlížečů z http://blog.chromium.org/. Pokud by měl Google na svém Chromium blogu odkaz na pingback, může pak server Mozzily automaticky odeslat zprávu o tom, že převzali jejich článek (např. díky tomu, že autor vyplní adresu do kolonky „zdroj článku“):
<link rel="pingback"
href="http://blog.chromium.org/pingback/">
nebo v HTTP hlavičce:
X-Pingback: http://blog.chromium.org/pingback/
Pokud pak Google uzná, že převzetí článku Mozzilou je oprávněné, mohou k danému článku přidat syndikační odkaz, čímž vytvoří skrytý zpětný odkaz:
<link rel="syndication"
href="https://blog.mozilla.org/blog/...">
Odeslání a přijetí pingbacku musí probíhat podle specifikace pomocí XML-RPC protokolu. Syndikace jsou většinou používány v spojení se zpravodajskými či informačními servery, které monitorují zajímavé blogy a následně zobrazují shrnutí jejich aktuálního obsahu (podobně jako fungují retweety).
Externí odkazy
Běžný odkaz na cizí stránku (tedy server třetí strany) běžně nemusíte nijak označovat.
Zakázaný „No follow“ („nenásleduj“)
Pokud odkazujete na stránku, kterou chcete zmínit, ale nechcete tím zlepšit její SEO pozici, můžete přidat atribut rel=nofolow
:
Podívejte se, jak by vaše stránka rozhodně
<a href=http://spatnyserver.com/ rel=nofollow>
neměla vypadat
</a>.
Pomocí nofollow
se dříve také označovali odkazy v reklamách nebo do obchodů, aby se tím nesnížilo SEO hodnocení stránky.
Důležité je uvědomit si, že nofollow
odkaz nijak nezakazuje přístup na danou stránku. Přeci jen odkaz je na stránce uvedený a jak se říká: „co je jednou na internetu už tam zůstane“. Používat tedy nofollow
například pro odkazy do administrace nemá smysl, protože vyhledávače mohou stránku stejně zaindexovat (jen se bude tvářit jako stránka bez referencí a bude mít nízké hodnocení).
Sponzorované odkazy
Od března 2020 můžete používat ještě další určení externích odkazů, které pak Googlu (a v budoucnu možná i dalším vyhledávačům) pomohou určit, jaký je váš vztah k danému serveru a jak by měl započítat jeho hodnocení.
První typ je sponzorovaný odkaz, který určuje, že na stránku neodkazujete proto, že se vám líbí, ale proto, že jste za to dostali zaplaceno nebo z toho máte jiný prospěch. Měli by tak být tedy označeny všechny reklamy nebo odkazy obsahující nějaký affiliate (např. odkaz do obchodu, kde dostanete procenta z prodeje):
Pokud vás recenze přesvědčila, můžete si ho rovnou
<a rel=sponsored
href="http://obchod.cz/produkty/123456.html?aff=moje_id">
koupit
</a>.
--------
Reklama:
<a rel=sponsored href="http://enlarge.it">
Pořiďte si větší nádobíčko.
</a>
--------
Podívejte se na náš
<a rel=sponsored href="http://jinyserver.cz">
spřátelený web
</a>
Uvědomte si, že vyhledávače určují vaše SEO podle vaše obsahu a jeho důvěryhodnosti. Pokud tedy máte na stránce reklamy nebo placené odkazy a neoznačíte je jako sponsored
nebo nofollow
a vyhledávač zjistí, že jde o reklamu (což není vůbec těžké, protože většina reklam vede na specifické adresy), může kvůli tomu snížit vaše SEO hodnocení z důvodu nedůvěryhodného (placeného) obsahu.
Uživatelské odkazy
Pokud máte na stránce sekci s komentáři, fórum nebo nějakou formu sociální sítě, kam vaši uživatelé mohou posílat vlastní příspěvky včetně odkazů, měli byste tyto odkazy označit příznakem rel=ugc
(„user generated content„, tedy „obsah od uživatelů):
<dt>Uživatel Jan Novák napsal:</dt>
<dd>
Tahle stránka o kočkách se mi líbí. Také mám
<a rel=ugc href="http://blog.cz/kocky">blog o kočkách</a>.
</dd>
Tím napovíte vyhledávači, že cíl odkazu není ve vaší režii a měl by být brán s rezervou. Může odkazovat na stránku týkající se stejného problému, ale stejně tak může jít o spam nebo nechtěnou formu propagace cizí stránky.
Více typů pro lepší určení
Výše uvedené typy odkazů můžete kombinovat podle potřeby. Například u reklamy, u které nemůžete ovlivnit obsah (a může tedy hrozit, že s jejím obsahem nesouhlasíte), můžete použít rel="nofollow sponsored"
. U uživatelských odkazů můžete použít rel="nofollow ugc"
, aby si uživatelé nemohli zlepšovat SEO uváděním odkazů na své stránky, nebo rel="sponsored ugc"
, pokud již víte, že jde ze strany uživatele o propagaci cizí stránky.
Vyhledávače pak všechny uvedené příznaky použijí k tomu, aby správně určili hodnotu odkazu (z hlediska SEO) a vztah vašeho a odkazovaného serveru (tzn. aby odkaz na špatný web nesnížil vaše vlastní SEO).
Přednačítání
Předchozí odkazy sloužily hlavně vyhledávačům a dalších službám, aby věděli, jak pracovat s výsledky. Další odkazy slouží naopak prohlížeči, aby věděl jak správně načíst současnou stránku nebo kterou další stránku pravděpodobně uživatel otevře a kterou by tedy mohl načíst dopředu.
DNS
Každý soubor na internetu je uložen na nějakém serveru, který má unikátní IP adresu. My, lidé, ale často místo IP adres používáme jména serverů, což je pro nás lépe čitelné a zapamatovatelné, ale počítačům to moc nepomáhá a musí si pak daná jména převést na, pro ně lépe pochopitelné, IP adresy.
Aby jim to šlo rychleji, můžeme prohlížeči poradit, které adresy by si měl dopředu přeložit, aby to nemusel dělat až v okamžiku, kdy z nich bude potřebovat stáhnout obrázek nebo skript.
<html><head>
<link rel="dns-prefetch" href="//mycdn.com" />
<link rel="dns-prefetch" href="//ajax.googleapis.com" />
</head>...
Těmito odkazy radíme prohlížeči, že stránka bude stahovat obrázky ze serveru mycdn.com
a javascripty z Google úložiště. Prohlížeč pak může rovnou zjistit, jaké jsou nejbližší servery pro obě CDN a až na stránce narazí na nějaký obrázek nebo JS soubor z daného serveru, rovnou bude vědět, z jaké IP adresy ho má stáhnout.
Prohlížeče a operační systémy obsahují DNS cache, takže překlad jména na IP adresu provedou pouze jednou (za určitou dobu, například 5 minut). Můžete tak zahrnout i jména serverů, které nevyžaduje přímo tato stránka, ale které budou potřeba v průběhu očekávaného procházení vašich stránek.
Připojení
Po té, co prohlížeč přeloží jméno serveru na IP adresu a před tím, než bude moci stáhnout požadovaný soubor, musí se s příslušným serverem domluvit na tom, jak spolu budou komunikovat. Prohlížeč musí poslat tzv. acknowledge request, pomocí kterého zjistí, zda požadovaný server existuje a je schopen a ochoten odpovídat na požadavky. V případě šifrovaného spojení (HTTPS) se ještě domluví na metodě šifrování a vymění si veřejné šifrovací klíče.
Pro označení, ke kterým serverům se bude stránka připojovat slouží odkaz preconnect
:
<html><head>
<link rel="preconnect" href="//mycdn.com" />
<link rel="preconnect"
href="//ajax.googleapis.com" crossorigin />
</head>...
Preconnect samozřejmě slouží i jako DNS prefetch, takže není potřeba uvádět oba odkazy; preconnect
by tak měl sloužit pro značení serverů, ke kterým se budete připojovat během načítání stránky, zatímco dns-prefetch
pro servery, které budete potřebovat až za nějakou dobu a není potřeba mít aktivní spojení hned. Aktivní spojení totiž stojí počítač určité zdroje, kterých nemá neomezeně, a navíc spojení po určité době (řádově jednotky až desítky sekund) vyprší a je potřeba ho obnovit.
Pokud víte, že spojení vede na server třetí strany (zpravidla CDN) a budete z něj stahovat skripty nebo data (pro obrázky to není potřeba), je potřeba ještě do odkazu uvést klíčové slovo crossorigin
, aby prohlížeč věděl, že nenavazuje spojení s vlastním serverem a příslušně to ošetřil. Více informací o crossorigin
komunikaci viz Ajax komunikace s jiným serverem.
Stažení souboru
Dále můžete prohlížeči poradit, které soubory budete na stránce potřebovat. Prohlížeč stahuje JS soubory a obrázky až v okamžiku, kdy jsou potřeba – např. pokud jsou JS soubory správně uvedeny až na konci HTML, prohlížeč je bude stahovat až v okamžiku, kdy vyrenderuje celou stránku a dojde k příslušnému script
tagu. Stejně tak stahuje obrázky až v okamžiku, kdy se zobrazí (např. pokud jsou ve výchozím stavu skryty).
My ale můžeme prohlížeči prozradit dopředu jména těchto souborů, a on pak v okamžiku, kdy nic nestahuje (a třeba zrovna renderuje část stránky z již staženého HTML a CSS), si může tyto soubory stáhnout a mít je připravené v cache. Až pak na konci souboru najde odkazy na skripty, nebude se muset zdržovat jejich stahováním:
<html><head>
<link rel="subresource" href="/script.js" />
<link rel="subresource" href="/logo.jpg" />
</head>...
Tím říkáme prohlížeči, že tyto dva soubory bude muset stáhnout v průběhu renderování stránky a je tedy nanejvýš vhodné, stáhnout je co nejdříve (hned, jak nebude potřeba stahovat nic, co potřebuje k synchronnímu renderování stránky).
Pokud chcete stáhnout obrázek nebo skript, který ale bude potřeba až později a není nutný k renderování stránky, můžete místo toho použít prefetch
, který začne soubory stahovat až po body.onload()
. Obvykle se používá pro soubory potřebné na dalších stránkách nebo pro části stránek stahované přes AJAX.
<html><head>
<link rel="prefetch" as="script" href="/js/script.js" />
<link rel="prefetch" as="image" href="/images/logo.jpg" />
</head>...
Zde říkáme, že budeme potřebovat soubory script.js
a logo.jpg
a že by bylo vhodné, kdyby je prohlížeč stáhl dopředu. Samozřejmě záleží na prohlížeči, zda to provede nebo nikoliv. To může rozhodnou např. podle rychlosti připojení, vytíženosti procesoru nebo dostupné cache. Aby se mu lépe rozhodovalo, můžeme do odkazu přidat hodnota as
, ve které řekneme, o jaký zdroj se jedná (obrázek, skript, atd.). Prohlížeč se pak může třeba rozhodnout, že dopředu stáhne skripty, protože ty musí zkompilovat než je bude moci použít, zatímco obrázky může zobrazit dynamicky během jejich načítání a nebudou tudíž tolik zdržovat.
Odkaz subresource
podporuje jen Firefox a Chrome (a jejich varianty jako Opera a Android browser). Naproti tomu prefetch
podporuje většina browserů kromě Safari a IE10 a starších.
Update: Chrome od verze 50 (duben 2016) podporuje nový typ preload
, který nahrazuje subresource
, a jde o novou specifikaci W3C, která odstraňuje určité nevýhody subresource
, takže by ji postupně měli podporovat i ostatní prohlížeče. Na rozdíl od subresource
můžete u preload
uvést atribut as
a určit tak, jak má prohlížeč stahovat soubor a jaké poslat hlavičky (např. u skriptu musí poslat origin
zatímco u obrázku to není potřeba, nebo naopak u obrázku poslat hlavičku, že podporuje WEBP formát, aby server mohl poslat menší obrázek místo JPG nebo PNG). Navíc u preload
můžete použít událost onload
a zpracovat načtená data před tím, než je budete potřebovat na stránce.
Pro podporu obou standardů ve všech verzích Chrome a Firefox můžete obě definice spojit:
<html><head>
<link rel="subresource preload" as="script"
onload="init()" href="/script.js" />
<link rel="subresource preload" as="image"
href="/logo.jpg" />
</head>...
<body>
...
<script src="/script.js" onload="init();"></script>
</body></html>
Odkazy na subresource
, prefetch
a preload
by se neměl používat na CSS soubory použité na dané stránce, protože ty by se měli stahovat hned na začátku, aby nebránili renderování stránky. Samozřejmě, pokud máte CSS, které bude potřeba až v průběhu prohlížení stránky (např. uvnitř obsahu staženého přes AJAX) nebo až na některé následující stránce, můžete ho také uvést do odkazu.
Renderování
Pokud jste si jisti, že uživatel z dané stránky půjde na jinou konkrétní stránku (např. je na druhé stránce článku a dá se předpokládat, že bude pokračovat třetí stránkou), můžete prohlížeči říct, aby danou stránku dopředu stáhl a nebo dokonce vyrenderoval. K tomu se používají buď odkazy prerender
(podporuje IE11+ a Chrome 35+) nebo prefetch as html
(Firefox 29+).
<html><head>
<link rel="prefetch" as="html" href="/dalsi-stranka.html" />
<link rel="prefetch" as="html" href="/vsechny-clanky.html" />
</head>...
Zde jsme prohlížeči řekli, že uživatel pravděpodobně půjde buď na další stránku nebo na seznam článků a tudíž by je měl prohlížeč dopředu stáhnout.
<html><head>
<link rel="prerender" href="/dalsi-stranka.html" />
<link rel="prerender" href="/vsechny-clanky.html" />
</head>...
Předrenderování je určeno výhradně pro zpracování celých stránek, takže již není potřeba uvádět atribut as
. V okamžiku, kdy pak uživatel klikne na odkaz na další stránku nebo seznam článků, nebude muset na nic čekat a další stránka nebo seznam se okamžitě zobrazí.
Oba zápisy je možno spojit tak, aby všechny prohlížeče rozuměli, co po nich chcete:
<html><head>
<link rel="prefetch prerender" as="html" href="/dalsi-stranka.html" />
<link rel="prefetch prerender" as="html" href="/vsechny-clanky.html" />
</head>...
Pro obě metody je samozřejmě potřeba mít správně nastavené cachovací hlavičky, aby se nestalo, že v okamžiku, kdy uživatel klikne na odkaz, bude již vyrenderovaná stránka stará a prohlížeč ji bude muset stáhnout znovu! Resp. je potřeba aby stránka měla nastaveno cachování alespoň na 5 minut, protože to je čas, jak dlouho je prohlížeč schopen předrenderovanou stránku udržet v paměti. Pokud na ni uživatel do té doby nepřejde, prohlížeč se rozhodne, že nebude plýtvat pamětí a vyrenderovanou stránku uvolní.
Během renderování fungují i skripty, takže můžete měnit DOM, přidávat prvky a odesílat requesty. Avšak v okamžiku, kdy se pokusíte ovlivnit něco vně stránky (např. uložit cookie, zapsat něco do localStorage, zobrazit uživateli alert nebo confirm, apod.), prohlížeč skript zastaví a nebude v něm pokračovat, dokud uživatel skutečně stránku nezobrazí. To je z toho důvodu, že pokud by se stránka ve skutečnosti zahodila (protože uživatel šel jinam), dostal by se prohlížeč do podivného stavu, kdy obsahuje data stránky, která se nikdy nezobrazila.
Určení pravděpodobnosti
Všechny výše uvedené odkazy (dns-prefetch
, preconnect
, prefetch
, prerender
) mohou obsahovat atribut pr
, kterým můžete určit pravděpodobnost (probability) toho, že bude daný zdroj potřeba pro zobrazení této nebo další stránky. Tedy alespoň podle specifikace (viz dále).
<html><head>
<link rel="dns-prefetch" href="//mycdn.com" pr="0.8" />
<link rel="dns-prefetch" href="//ajax.googleapis.com" pr="0.5"/>
</head>...
Zde jsme prohlížeči poradili, že pravděpodobnost připojení k serveru mycdn.com
je 80%, zatímco k Google jen 50%. Pokud se tedy prohlížeč rozhodne překládat dopředu DNS adresy, měl by začít adresou mycdn.com
, protože je větší pravděpodobnost, že bude potřeba (nebo bude potřeba dříve).
Stejně tak například s předrenderováním stránek:
<html><head>
<link rel="prerender" href="/dalsi-stranka.html" pr="0.5" />
<link rel="prerender" href="/vsechny-clanky.html" pr="0.3" />
</head>...
Zde jsme prohlížeči sdělili, že pravděpodobnost, že uživatel půjde na další stránku je pouze 50% (což jsme např. zjistili z Google Analytics nebo jiného monitorovacího nástroje), že půjde na seznam článků je 30% a zbylých 20% uživatelů buď stránku opustí nebo půjde někam jinam (galerie, kontakt, apod.). To, že uživatel má 50% šanci jít na danou stránku a že 50% uživatelů půjde na danou stránku, jsou jen dva různé zápisy téhož statistického údaje.
Díky tomu se může prohlížeč lépe rozhodnout, jaké zdroje by měl dopředu stahovat nebo renderovat a nebo v jakém pořadí, by to měl provádět.
Skutečná podpora
Z výše uvedeného určení pravděpodobnosti by se mohlo zdát, že vy, jakožto programátor, do stránky jednoduše vypíšete desítky odkazů na prefetch
a prerender
s pravděpodobnostmi, a prohlížeče si pak vyberou, co vše stáhnou. To by bylo ideální.
Skutečnost je však jiná. U prerender
většinou platí, že pokud je ve stránce jeden prerender
, prohlížeč ho stáhne a vykreslí; pokud je jich ale více (s pravděpodobnostmi), prohlížeč nic nerozhoduje a na nějaké stahování se vykašle. V Internet Explorer ještě můžete pomocí JS (viz níže) určit jinou (druhou) stránku, pokud na základě chování uživatele zjistíte, že asi provede něco jiného (např. ohodnotil článek 1 hvězdičkou, takže se dá předpokládat, že další stránku článku už číst nebude); ale opět, pokud vložíte do stránky více než jeden odkaz, prohlížeč je bude ignorovat.
Stejně tak u prefetch
si každý prohlížeč vybere několik prvních odkazů, které stáhne a ostatní ignoruje. Není tedy dobré se na tuto vlastnost spoléhat a pokud můžete, je lepší si zdroje stahovat a cachovat pomocí JS nebo AJAXu. Pro zobrazení HTML stránky můžete použít Zobrazení staženého HTML.
Dynamické přednačtení
Co když nejste v okamžiku přípravy stránky (např. v PHP skriptu) schopni rozhodnout, jaké další stránky uživatel navštíví nebo jaké zdroje bude potřeba?
Můžete samozřejmě přidávat odkazy i dynamicky pomocí javascriptu:
if (mypage.user.willVisitNextPage()) {
link = document.createElement('link');
link.setAttribute('rel', 'prerender');
link.setAttribute('href', 'dalsi.html');
document.getElementByTagName('head')[0]
.appendChild('link');
} else {
$('link[href=dalsi.html]').remove();
}
Stejně tak můžete i odkazy odebírat v případě, že zjistíte, že uživatel danou stránku nenavštíví nebo že daný zdroj nebude potřeba. Pokud prohlížeč ještě danou stránku nebo soubor nestáhl, nebude tak již zbytečně plýtvat čas jejich stažením.
Přednačtení skriptů
Co se týká skriptů, můžete místo uvedení prefetch
v hlavičce a následného uvedení skript
na konci HTML použít opožděné spuštění. To je vhodné v případě, že daný skript neprování nic, co přímo zasahuje do stránky, a ani nevyužívá žádné další zdroje (např. jQuery knihovnu), a pouze poskytuje další podporu (např. měření přes Google Analytics, apod.).
Běžně načítáme skript pomocí:
<script src="/js/script.js"></script>
Což pro prohlížeč znamená, že musí soubor stáhnout, zkompilovat, vykonat daný skript a pak teprve může pokračovat se zpracováním a renderováním HTML. Pokud ale nepotřebujeme pozastavit zpracování HTML k tomu, aby skript fungoval, můžeme ho nechat stáhnout asynchronně:
<script async src="/js/boom.min.js"
onload="boom.init();" ></script>
Zde stahujeme (smyšlenou) knihovnu Boom, která nevyžaduje, aby byla spuštěna okamžitě. Řekneme tedy prohlížeči, že má na pozadí stáhnout daný soubor a po jeho zkompilování spustit funkci boom.init()
, která je v daném souboru nadefinována. To díky tomu, že obsah hodnoty onload
je vyhodnocen (eval(this.onload)
) až když je potřeba a tak může odkazovat na funkci, která ještě neexistuje a bude vytvořena až po stažení souboru.
Důležité je, že asynchronně stažený soubor bude zpracován hned, jak bude stažen. Není tedy jisté, kdy a v jakém pořadí budou jednotlivé asynchronně stažené funkce volány!
Jen pro pořádek: zápis boom.init()
neodkazuje na jméno souboru, ale na namespace, který je v souboru definován:
//boom.js
window.boom = {
init: function() { ... }
};
Pokud naopak potřebujete určitý skript zavolat až po načtení stránky (body.onload()
), můžete použít odložené stažení skriptu:
<script defer src="/js/clock.min.js"
onload="clock.start();" ></script>
Tento kód stahuje skript clock.js
, který na stránce animuje hodiny (oblíbený to prvek každého začínajícího skriptaře). Jelikož ale hodiny mohou začít běžet až po vyrenderování stránky, není potřeba je spouštět hned v kódu. Pomocí defer
tedy řekneme, že příslušná onload
událost se má vyvolat až po dokončení body.onload()
události.
U defer
skriptů je důležité, že se vyvolají přesně v tom pořadí, v jakém byly ve stránce uvedeny; je tedy možné stáhnout několik defer
skriptů, které jsou na sobě závislé (např. jQuery, jQuery Mobile a poté vlastní aplikační skripty).
Naopak je potřeba si uvědomit, že prohlížeče, které async
a defer
nepodporují, budou skripty zpracovávat synchronně a okamžitě. Tudíž i skript, který se stahuje jako defer
, by měl na začátku ověřit, že již bylo dokončeno načítání stránky a pokud ne, zařadit se do body.onload()
fronty:
//clock.js
window.clock = {
start: function() {
if (document.readyState == 'complete') {
clock.prepareHtml(); //spusť hodiny
}
else { //čekej na načtení stránky
window.addEventListener('load',
clock.prepareHtml, false);
}
};
Přednačítání přes hlavičky a HTTP/2
Výše uvedené přednačítání nemusíte vkládat do HTML, ale můžete podobným způsobem vložit odkazy do HTTP hlavičky:
HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Link: </img/logo.jpg>; rel=preload; as=image
Link: </css/layout.css>; rel=preload; as=style
Díky tomu bude prohlížeč vědět, které soubory musí stáhnout ještě před tím, než začne parsovat samotné HTML v těle odpovědi a samozřejmě se tím o pár milisekund urychlí jejich načtení.
Navíc, pokud máte server, který podporuje HTTP/2 a jeho funkci HTTP/2 push, uvedení takové hlavičky způsobí, že server místo odeslání hlavičky daný soubor přímo přiloží na konec HTML odpovědi a urychlí tak jeho načtení:
HTTP/2.0 200 OK
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
<html>...html body...</html>
... obrázek /img/logo.jpg
... styl /css/layout.css
Server podporující HTTP/2 musí danou Link
hlavičku vymazat, protože jinak by si mohl prohlížeč o daný soubor zažádat znovu, i když ho již dostal v rámci HTML odpovědi.
Vložení souboru do HTTP/2 push se v PHP provádí následovně:
<?php
ob_start(); //umožní odesílání hlaviček v kódu
header("Link: </img/logo.jpg>; rel=preload; as=image", false);
echo '<img src="/img/logo.jpg" alt="logo firmy">';
header("Link: </css/layout.css>; rel=preload; as=style", false);
echo '<link rel="stylesheet" type="text/css"',
' href="/css/layout.css">';
ob_end_flush(); //odešle HTML odpověď
Pro odesílání přednačítacích (a HTTP/2 push) hlaviček jsou důležité 2 věci:
- Musí být zapnuté cachování odpovědi (
ob_start()
) a nebo musíte jiným způsobem zajistit, aby se odpověď neodeslala dříve než vložíte všechny potřebné hlavičky. - Druhý parametr funkce
header()
musí býtfalse
, aby se hlavička přidala na konec místo aby se přepsala již existující. Jinak by totiž hlavička pro CSS smazala předchozí pro obrázek.
To, zda server odešle jen hlavičku nebo přímo soubor záleží na tom, jestli prohlížeč i server podporují HTTP/2.
Pozor ale na to, že nevýhoda HTTP/2 push je v tom, že neumožňuje prohlížeči využít vlastní cache. Pokud tedy na každé stránce přiložíte do odpovědi logo a CSS, bude to znamenat, že každá stránka bude větší a bude se stahovat déle.
Obejít se to dá například tím, že HTTP/2 push (tedy přednačítací hlavičky) použijete jen během prvního („cold„) načtení (což se dá např. poznat podle existence SESSION COOKIE
v prohlížeče.