Přejít k navigační liště

Zdroják » Webdesign » Přepište historii webových stránek

Přepište historii webových stránek

Články Webdesign

Samozřejmě máme na mysli tu historii, co je uložena v prohlížeči a ke které se dostane uživatel tlačítkem „zpět“. Vysvětlíme si, proč je v adresách některých webových služeb použita na pohled podivná konstrukce „/#!“, k čemu slouží a jaká jsou její úskalí.

Konstrukce #! se nazývá hashbang (též shebang) a je známá uživatelům UNIXu, ovšem jaký je její význam v URL? Co přesně znamená na Twitteru adresa http://twitter.com/#!/zdrojak a proč je takto podivně zapsaná?

URL fragment

URL fragment je volitelná část adresy, uvedená za znakem hash (#).

http://www.example.com/foo/bar/page.html#fragment
qrcode

K článku není ukázka

K článku není k dispozici zdrojový kód

Při otevření takového odkazu se stránka posune tak, aby byl viditelný prvek s identifikátorem fragment (např. <div id="fragment">), popř. kotva s tímto jménem (<a name="fragment">).

Tato část URL má oproti zbytku adresy dvě zvláštnosti:

  1. nepřenáší se v HTTP požadavku na server; pro stránky /foo/bar/page.html#fragment nebo /foo/bar/page.html#naprosto-cokoli bude požadavek stejný jako pro stránku /foo/bar/page.html
  2. při změně této části URL se neprovádí reload načtené stránky, ale objeví se v historii

Tyto zvláštnosti nabízejí zajímavé možnosti pro moderní stránky, postavené na dynamickém načítání obsahu, např. AJAXem.

V dobách, kdy bylo běžné každý požadavek (klik na odkaz, odeslání formuláře apod.) odesílat na server (a mnohé knihovny a frameworky tak dosud fungují), se mohlo zdát, že fragment ztrácí na významu. U aplikací, které ale dynamicky načítají obsah ze serveru bez reloadu, se právě tato část adresy nabízí k tomu, aby si skript na straně klienta ukládal potřebné stavové informace, a přitom se nenačítala stránka znovu.

Radikální pohled na webové aplikace dokonce hovoří o tom, že aplikace by se měla skládat z pouhé jedné stránky – viz Single Page Interface Manifesto. Argumenty, které nabízí, znějí rozumně – například: když se obsah stránky mění neustále pomocí AJAXu, a URL přitom zůstává stále stejné, co se stane, když si ho někdo uloží do oblíbených? (Přesto je pro mnohé takový pohled na webové aplikace natolik neobvyklý, že je potřeba vydávat manifesty – nabízí se paralela s Dogma W4 – pozn.aut.)

Google Hashbang

Potřeba indexovat různé stavy AJAXových webových aplikací vedla Google k návrhu Making AJAX Application Crawable. V této specifikaci navrhuje serverům dohodu: Servery budou pro určité stavy aplikace používat rozlišení pomocí URL fragmentů, ale zároveň tyto stavy nabídnou vyhledávačům v podobě „HTML snapshotů“.

Příklad: AJAXová aplikace nabízí, řekněme, kalendář pro určité dny. Aktuálně otevřený den si poznačí v URL fragmentu, např. takto: kalendar.html#den=20110211. Pro vyhledávač je taková adresa „černou dírou“ – bez další pomoci tam uvidí jen prázdnou kostru HTML stránky s JavaScriptem.

To, že stránka dodržuje tuto „dohodu“, dá na vědomí právě tím, že místo klasického hashe (#) použije hashbang (#!). Tedy kalendar.html#!den=20110211. Tím dá najevo Googlu, že může požádat o HTML snapshot takové adresy. Ten tak učiní tím, že pošle vyhledávacího robota na adresu kalendar.html?_escaped_fragment_=den=20110211. Váš server by se měl postarat o to, aby na tento dotaz vrátil zhruba totéž, co uvidí uživatel na výše uvedené adrese s fragmentem.

Bližší informace o této technice naleznete v dokumentu Googlu. Ve stručnosti lze říct, že u adres s hashbangem prochází Google i „ošklivý“ tvar URL, kde část za hashbangem předává jako parametr _escaped_fragment_.

Pokud stránka sama nemá „hashbangovou“ adresu, ale přesto ji chcete v této podobě Googlu nabídnout, vložte do hlavičky META tag fragment.

<meta name="fragment" content="!">

Takovou stránku Google zaindexuje i s _escaped_fragment_ podobou.

Kde hashbang potkáme?

Tento tvar začínáme potkávat na stále větším počtu serverů – od Facebooku přes Twitter (http://twitter.com/#!/zdrojak)až po, nejnověji, LifeHacker.

Výhodou takto napsané aplikace je, že statický obsah (např. obrázky, styly apod.) se po změně URL fragmentu nenačítá znovu. Např. Twitter tak může pozadí, prvky UI a další věci načítat pomocí statických adres, a konkrétní obsah, donačítaný AJAXem, rozlišuje pomocí části za hashbangem. Můžete si ostatně zkusit přepsat to uživatelské jméno na jiné – uvidíte, že se stránka nenačítá znovu celá, pouze se pomocí XHR dočítá obsah. Další výhodou pak je to, že tyto změny jsou ukládány do historie prohlížeče; uživatel tak může procházet historií, aniž by se stránka načítala ze serveru znovu.

Hezké vysvětlení principu hashbangu naleznete např. na StackOverflow.

Technologie z rodiny HTML5 nabízejí obsluhu změny URL fragmentu – viz např. onhashchange či specifikace history events.

Úskalí

Velmi pěkně popsal problémy, spojené s „hashbangováním“ adres, Mike Davies ve svém článku Breaking the Web with hash-bangs. Svá tvrzení ukazoval na příkladu již zmíněného webu Lifehacker. V článku argumentuje proti využívání takových URL.

Adresa http://lifehacker.com/1234/nova-stranka se změnila na http://lifehacker.com/#!1234/nova-stranka. Mike Davies tuto změnu kritizuje – namísto dodržování principu „každá stránka má vlastní adresu“ je náhle vše jen na titulní stránce, a – duplicitně – na „zkomolené“ adrese. Dalším problémem je to, že takový obsah nedokážou agenti (mimo prohlížečů), splňující HTTP/1.1, procházet – s výjimkou Googlebotu. Namísto obsahu vidí jen prázdnou stránku, resp. stránku se statickým obsahem.

Nefunguje správně ani cachování obsahu, protože obsah nemá kanonickou reprezentaci. Navíc je takový web závislý na fungujícím JavaScriptu. Chyba ve skriptech znamená, že váš web uživatelům nebude fungovat – zapomenutý console.log nebo zapomenutá čárka na konci prvků pole znamená, že pro velkou část vašich návštěvníků bude web nefunkční a uvidí jen prázdnou stránku. Pokud máte na webu reklamu, upozorňuje Davies, jste vydáni všanc JavaScriptovým kódům, které vám reklamní síť posílá, a je dobře známé, že tento kód bývá technicky ten nejhorší odpad, co se na webu vůbec vyskytuje.

Závěr

Hashbang ano nebo ne? Jako ve spoustě jiných případů, i zde platí: záleží na okolnostech. Jsou situace, kdy je jeho použití rozumné a na místě, a jsou situace, kdy jeho bezdůvodné použití přinese převahu negativních efektů. Neexistuje univerzální pravidlo ani univerzálně použitelná pravda, a záleží na zkušenostech každého vývojáře.

Komentáře

Subscribe
Upozornit na
guest
20 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Honza

Vzdyt to jde i bez toho, vsechny ty vyhody tu popsane nejsou ani v nejmensim zavisle na # ale daji se pouzit i s normalni a platnou url (dynamicky reload jen casti stranky, pohyb v historii) – viz treba pohyb po adresarich a souborech na githubu:
https://github.com/django/django/tree/master/django/conf

karf

Github používá HTML5, které tuto možnost zavádí. Čili je to novinka, která ve starších prohlížečích nebude fungovat. Workaround s hashem byl vymyšlen dávno před tím, než tohle vzniklo.

Michal

Nechapu. Pohyb po filesystemu projektu na githubu je resen standardnimi odkazy

fos4

Zkus to ve chromu.

karf

To co předvedl Lifehacker je odstrašující příklad, jak by se to dělat nemělo. Pro dobrou implementaci je potřeba mít solidní model pro práci se stavy v JS. Ten by měl zajistit konzistentní chování (zobrazení stránky včetně obsahu) v případech, kdy: kliknu na tlačítko zpět, dopředu, vrátím se o X kroků v historii, přejdu na úplně jiný web a pak se zase vrátím, uložím si stav do záložek a vrátím se na něj jindy, stisknu kdykoliv F5, pošlu někomu odkaz s hashem, atd.

Anonymous Coward

Tady je k tomu ještě pěkné čtení: http://www.isolani.co.uk/blog/javascript/BreakingTheWebWithHashBangs

Celkově mám pocit, že je to nehezké řešení neexistujícího problému. Oproti normálním adresám je to mnohem složitější, náchylnější k chybám a méně pohodlné.

Anonymous Coward

Mea culpa, mea maxima culpa. Slibuju, že příště budu číst pořádně a nepostovat duplicity.

Je to možné

Je to pravda a ikdyž to není úplně snadné, je to možné. Právě na takové stránce pracuju a vážně všechny tyto vlastnosti splňuje.

robot0001

Tento plugin do jQuery se mi celkem osvědčil, kdyby to někomu pomohlo: http://tkyk.github.com/jquery-history-plugin/

Murdej

Řešení by bylo při generování první stránky použít
http://example.com/neco/!dalsi-parametry

a až načtení všech skriptů skriptem změnit na
http://example.com/neco/#!dalsi-parametry

tímto by se prohlížeče bez js a roboti dostali na svůj obsah.

V případě některých chyb by se skript nespustil takže by odkazy byly pořád funkční.

Wlada

No tam je problem s tim, ze zmenit adresu z http://example.com/neco/!dalsi-parametry na http://example.com/neco/#!dalsi-parametry znamena reload stranky a tedy nove nacitani skriptu.

Ale jinak treba s tou nefunkcnosti to ja osobne resim tak, ze vsechny stranky standardne odkazuji na http://example.com/?!parametry a teprve pri nacteni tam dam javascriptem onclick presmerovani na http://example.com/#!parametry, takze v pripade, ze v js dojde k chybe, tak web funguje normalne dal jen neajaxove (stranky s ?! jsou shodne se strankami s ?_escaped_frag­ment_).

František Kučera

1) Nevím, jaký mají dojem ostatní, ale můj „uživatelský prožitek“ (hrozný výraz) např. z nového Twitteru je citelně horší než z toho starého –
na to, že stránka obsahuje pár odstavečků textu a vpravo nějaké ikonky, se načítá nesmyslně dlouho.

2) V době, kdy po síti létají gigabajty porna, warezu a nesmyslných uživatelských videí atd., mi přijde trochu zbytečné řešit, jestli se nějaký kousek (X)HTML nebo CSS přenese jednou nebo X krát – stále je to totiž zlomek toho datově náročného obsahu (ať už legálního nebo nelegálního).

3) Ano, technika donačítání stránek AJAXem může pomoci, aby z toho měl uživatel lepší pocit, taky už jsem zažil stránky, které se takhle načítají a fungují velmi rychle – ale stejně tak znám jiné weby, kde se načítá vždy celá stránka, přesto je web velmi svižný – stránky jednoduše nejsou zanesené „moderním“ balastem (pozor, tím nemyslím nějaké holé HTML, kde autor zcela ignoroval formu a věnoval se jen obsahu – minimalistický/jed­noduchý/úspor­ný web není totéž co hnusný web).

4) Cílem může být ušetření práce serverům (aby nemusely sestavovat vždy celou stránku) na úkor klientů. To mnohdy dává smysl – domácí uživatel s nabušeným pécéčkem s tím nebude mít problém a serveru to citelně pomůže (server je sice taky nabušený, ale připadá na něj mnoho uživatelů – zatímco ten Pepa sedí doma u svého čtyřjádra sám). Jenže ve chvíli, kdy se chceme vydat cestou energeticky úsporných tenkých klientů nebo mobilních zařízení s dlouhou výdrží, je tahle myšlenka najednou kontrarevoluční – ulehčíme serverům na úkor klientů, jenže ta zařízení dostatečný výkon nemají resp. vede to k tomu, že i na obyčejné prohlížení webu bude zase potřeba relativně silný počítač. Nicméně tohle převalování se ze strany na stranu je asi údělem IT…

limit_false

Do kamene tesat.

Navic je #! strasny opruz s NoScriptem. Treba twitter ma i non-hashbang verzi, ale je to opruz to prepisovat. Lze vytvorit greasemonkey script, co to bude prepisovat, ale je to taky opruz. Nechapu proc to zrovna twitter potrebuje. Stejne RS. Puvodni web byl stokrat lepsi a prehlednejsi.

František Kučera

A nešlo by to přepisovat pomocí HTTPS Everywhere? Jeho pravidla sice slouží k přepisování na HTTPS verzi, ale možná by to šlo použít i na tohle.

limit_false

Jasne, slo by to s HTTPS Everywhere, ale to neni na to uplne urceno. Navic je tam porad bug, kdy se „jaksi zapomene“ z cookie udelat secure cookie v nekterych pripadech.

Naklonoval jsem si i git z HTTPS Everywhere, ale mel jsem na to jenom nejakou hodku zatim, takze jsem to nenasel, proc to nastava (nemam prilis zkusenosti s debugovanim FF extensions).

S tim hashbangem by se to vic hodilo do NoScriptu, uvazoval jsem dat to jako feature-request with donation. Jednoduse by se to udelalo jako option, ze pokud site neni ve whitelistu, prepise se to jednoduse odstranenim hashbangu.

Odstraneni hashbangu funguje na mnoho sajtu, ale treba zrovna na RS ne. Proste je to celkem pruda opravovat to, protoze si kazdy sajt udela ad-hoc reseni. Je to jako hadat co si mysli nahodne orakulum v NP relativizovanem nahodnym orakulem (viz Baker-Gill-Solovay).

vkalina

Asi jsem zpátečník anebo konzerva, ale nějak mi uniká, proč by crawlery měly indexovat obsah aplikací. Na webu jsou stránky buď dokumentové, kde návštěvník může najít informace (a proto je vyhledávače indexují), anebo „web 2.0 aplikace“. U těch prvních nevidím ani nejmenší důvod, proč by měl být celý web v jedné stránce a obsah načítat AJAXem. Umíte si třeba představit wikipedii celou v AJAXu? Jaký by to mělo přínos? U webových aplikací, kde to dává smysl (typicky třeba mapové servery anebo třeba translate.goo­gle.com), tam ať se fragmenty používají, od toho jsou, ale tam zas nechápu, proč by to měly indexovat vyhledávače, když obsah je více-méně pokaždé jiný, často privátní a pro cizího kolemjdoucího čtenáře tam asi zřídka kdy budou užitečné informace.

Nebo mi někdo může vysvětli smysl, proč je ten lifehacker.com udělaný tak jak je udělaný? Díky.

OldFrog

Souhlas.

washeck

Já kupříkladu řeším tento problém: Mám mapovou aplikaci, která má jako doplňkovou část blog s články o mapě, některých jednotlivých místech v ní, nápovědou k aplikaci atd. Požadavek je, aby při otevření blogu nedošlo ke ztrátě kontextu mapy (poloha, zapnuté vrstvy, otevřený popup). Proto se blog otevírá v části stránky pomocí jQuery Overlay.

V původním návrhu měl odkaz na blog z mapy metodu onClick, které ho otevřela. Nyní je to dělané přes hash (http://example.com/#clanek=id), kdy javascript zaznamená změnu hashe, rozparsuje ho a otevře overlay. Jenže takto udělaný blog není indexovaný crawlerem, což je škoda.

Jakub Vrána

Škoda, že podpora indexování AJAXového obsahu přichází prakticky až v momentě, kdy existuje mnohem lepší řešení, které se začíná i zvolna prosazovat (Chrome, Firefox 4). To řešení spočívá v metodě history.pushSta­te, pomocí které lze změnit kompletní URL, aniž by to vedlo ke znovunačtení stránky ze serveru. To je na rozdíl od manipulace s hashem stránky zcela čisté řešení už jen proto, že hash slouží pro odkázání na část stránky.

Výhody jsou očividné – stejné URL pro všechny, žádné problémy s indexováním, žádná nutnost zpracování magického parametru _escaped_frag­ment_, pěknější a smysluplnější URL.

Vyzkoušel jsem toto řešení v Admineru (bude součástí verze 3.2.0) a jsem z něj nadšen – pro uživatele všechno funguje zcela transparentně, jen je to v podporovaných prohlížečích ještě rychlejší. Pokud mi čas dovolí, tak bych se své zkušenosti pokusil sepsat do článku.

imploder

To je dobrá zpráva, ale ještě dlouho bude potřeba myslet na starší prohlížeče. Firefox 4 ještě ani nevyšel.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.