

Breaking the web with hash-bangs - Terretta
http://www.isolani.co.uk/blog/javascript/BreakingTheWebWithHashBangs

======
raganwald
I accept the brittleness of a content-oriented site switching to a javascript-
driven SPI implementation, however I'm confused by the assertion that the
strongest reason to switch is because it's cool. I can't speak for Gawker, but
some sites may switch because they want the browser to do more of the
rendering work, such as rendering templates. Others may want to avoid the
overhead with a full page refresh as users navigate the site.

The author clearly dislikes what's going on, and the post would be stronger if
he simply stated the disadvantages and let others speak to the benefits rather
than putting up a strawman and claiming that people implement this sort of
site because it's cool.

~~~
ZoFreX
The author does his point a disservice by being under-informed, imo. I agree
that Gawker's redesign is horrible, and share his hate of needless javascript
(why re-implement half the browser stack?), but his suggestions for
improvement would actually be a reduction in functionality.

He suggests using real URLs - instead of "/#!5753509/hello-world-this-is-the-
new-lifehacker" we would have "/5753509/hello-world-this-is-the-new-
lifehacker". Sounds great, but what happens when you click to a new article,
which is loaded with AJAX?

> Engineers will mutter something about preserving state within an Ajax
> application. And frankly, that’s a ridiculous reason for breaking URLs like
> that.

Is it? Let's try things all possible ways (with the assumption that content is
loaded via AJAX) and see what happens. Firstly, the current state:

Address bar: "/#!5753509/hello-world-this-is-the-new-lifehacker", click on a
link, now it's "/#!downloads/5753887". I can bookmark this, send the link to a
friend, etc etc.

Option two is to not track this at all, after all preserving state isn't that
important, right?

Address bar: "/#!5753509/hello-world-this-is-the-new-lifehacker", click a
link, it doesn't change. I can't bookmark the new page, I can't send the link
to a friend, my back button won't work properly.

Third option is to use real URLs as he suggested... we need to track state
(otherwise we hit the same problems in option 2) so let's try that: Address
bar: "/5753509/hello-world-this-is-the-new-lifehacker", click a link, it now
contains "/5753509/hello-world-this-is-the-new-lifehacker#!downloads/5753887".
Oops. That's even less clean.

Conclusion: If you must load content with AJAX, using URL fragments to track
state is the most functional and cleanest-URL option available.

~~~
sjs
> He suggests using real URLs - instead of "/#!5753509/hello-world-this-is-
> the-new-lifehacker" we would have "/5753509/hello-world-this-is-the-new-
> lifehacker". Sounds great, but what happens when you click to a new article,
> which is loaded with AJAX?

I would deliver the page with plain old HTML links to other pages. On page
load I'd use JavaScript to see if the new pushState[1] API is available, and
if so fetch the JS required to update the page dynamically and then update the
link elements to do the AJAXy thing. Seems like it would degrade gracefully in
old browsers and keep the URL current in new browsers.

[1]
[https://developer.mozilla.org/en/DOM/Manipulating_the_browse...](https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history)

edit: is sjs382 my doppelganger?! (or vice versa)

~~~
ZoFreX
Yes, if I were forced to use JS for loading the primary content I would do
that too. There are a couple of options for doing so if you don't want to roll
your own (and you don't - it is actually a very complex thing to get working
cross browser), JQuery History [1] which is nice and simple, and JQuery BBQ if
you need a bit more control.

Personally I think it's a little early for pushState, and degrading to #! is
really ugly, so for now I would say just use normal page loads like everyone
else unless you have a really good reason (good reason: GMail. bad reason:
glorified blog.)

[1] <http://tkyk.github.com/jquery-history-plugin/> [2]
<http://benalman.com/projects/jquery-bbq-plugin/>

~~~
sjs
Agreed. I meant degrade to regular URLs, not the #! thing. IMO you don't need
the #! for something as simple as switching articles.

------
jbermudes
Looks like gawker sites show up pretty much empty with javascript turned off,
and on top of it there's no warning that it has to be turned on? What ever
happened to graceful degradation? Give me 1996 text only if you have to, but
please, don't break the web by forcing javascript. Even Gmail, the poster
child for javascript/Ajax detects that you have it disabled and shows you an
HTML-only version.

------
burgerbrain
Can someone explain to me why a site like lifehacker even needs javascript at
all, let alone so much? It's a _blog_ , presumably it's value _should_ come
from the value of it's textual and pictorial content.

It's just _nuts_ that I have to burn so much CPU just to read some text.

~~~
garry
The web is evolving to provide media experiences that are lower latency and
much more exploration oriented. No page reloads and greater interactivity are
the first step.

~~~
burgerbrain
All of that adds exactly zero to the actual content of the blog. You know,
'content', the stuff I actually visit blogs for.

Furthermore, I've _never_ been annoyed at page reloads while reading a blog.
Now their shitty transition crap?... There is nothing "lower latency" here.

~~~
silversmith
Sending a e-mail does not add any real 'content' over telegraphing the same
message. It's just a change of presentation layer. I still would rather send
e-mails.

And the same way I would rather create JS-driven sites. It allows me to be
more creative with the presentation, while staying in the comfort zone of
HTML/CSS/JS. Offloading work from my servers to the computers (that, based on
my experience, are near-idle while browsing) of end users is a nice benefit.

Oh, and I would disagree about the 'There is nothing "lower latency" here'
statement. I visited lifehacker.com out of curiosity, and noticed something:
with JS navigation, I could scan headlines in the sidebar while the article
was loading, something I would not be able to do while a 'traditional' page
was rendering.

Of course, it's not a general rule. There are projects where you support
IE6/7, and then there are projects where you don't give a damn whether it
works for anything but edge versions. Same with using JS as presentation
layer.

~~~
cousin_it
> _with JS navigation, I could scan headlines in the sidebar while the article
> was loading, something I would not be able to do while a 'traditional' page
> was rendering._

...Wha? You can make traditional pages that display progressively just fine.
In fact that's the default mode of operation for HTML and was supported as far
back as Netscape 1.0. What's it with people, why do they keep forgetting about
sensible architectural decisions just because they were made long ago? Or am I
just getting old?

~~~
jarek
Most web programmers have always had the attention span of a goldf-- ooh shiny
thing!

------
drdaeman
Even not considering that HTML5 History API, is it hard to just consider
"/1234/spam" and "/#!1234/spam" synonymous and use the latter when you
navigate with JavaScript enabled?

I.e.:

1\. You visit "/1234/spam", and get served full HTML page with some (optional)
JavaScript for progressive enhancement.

2\. You click on "/4321/ham" link, but JavaScript hooks it up and replaces URI
with "/#!4321/ham" (if your browser don't support HTML5 history API, of
course). Yes, there is one full-page reload.

2.1. (Alternative) Or - even better - you can be redirected to "/#!1234/spam"
on step 1, so you won't notice the glitch on your first click.

3\. You continue to navigate with AJAX, now without reloads. You can bookmark
pages and so on (and if you somehow happen to lose JavaScript support you
could just remove "#!" to get a valid URI).

Very simplified implementation cost:

1\. `$("a[href]").attr("href", function() { return
this.href.replace(/^\/(?!#)/, "/#!"); });` on every page

2\. `if (location.pathname === "/" and location.hash.match(/^\/#!/) {
$("#content").load(location.hash.replace(/^#!/, "/") + "?format=content-
only"); ... }` on / page.

3\. Ability to return undecorated ("article-only") content on
`/1234/spam?format=content-only` requests.

~~~
Pewpewarrows
You just described exactly what you're _supposed_ to do in a progressively-
enhanced single-page Javascript application. Build the existing site first
without a single line of js, develop the hash-bang/HTML5 history syntax on top
of it, and replace the links if javascript exists.

The Gawker family of sites failed at doing all of this.

------
antimatter15
I was building an app that used pushState/replaceState recently instead of the
hash bang syntax, but getting content navigation isn't easy. For example, when
attaching the event handler to the links, you have to be careful not to make
it trigger on middle or right clicks and you have to keep track of the scroll
state so going back keeps the same behavior and also to take a copy of the
previous selected text. Without all of that, intra-page navigation feels
unnatural and uncanny.

~~~
strager
Good points, but it seems some of that (scrolling, selection, form data, etc.)
should be left to the browsers to fix/implement/deal with. Granted, it _is_ a
really bad user experience.

Seems like this should be made a JS library in the meantime. (Hint, hint. =])

------
hybrid11
We had a similar problem with our site, and we solved the issue by using <a
id="linkID" href="pathToContent">title</a> links with a jQuery event handler
that prevents the default behavior of the link.

With this implementation, when the link is clicked the appropriate content is
served through an Ajax call, and the crawlers are able to index the content.

You can see it in action here <http://lynkly.com>

~~~
pnathan
I like the smooth two-column layout and flow. It's very high class.

------
timb
Newer browsers ( <http://caniuse.com/#search=history> ) can manipulate the url
without needing the #! hack.

~~~
raganwald
To be specific, it's just the # hack, or fragment hack if you like. The bang
leading the fragment is a Google-specific thing to help the Googlebot crawl
your content.

[http://stackoverflow.com/questions/3009380/whats-the-
shebang...](http://stackoverflow.com/questions/3009380/whats-the-shebang-in-
facebook-and-new-twitter-urls-for)

~~~
Yaggo
<strike>No, timb was referring to HTML5 history api. It makes possible to
alter the path component of a URL by javascript, eliminating the need for #
hack. Try browsing repositories on github with WebKit-based browser to see a
real world example.</strike> (sorry for my misreading)

~~~
ehsanul
And raganwald was referring to the '#!' hack, since it's really just the '#'
hack. He wasn't addressing the history api.

------
poink
The more complex your site gets, the harder making /foo/bar => #!/foo/bar
dance becomes. This is hampered by the fact that, when you bring these issues
up with business folks, it'll probably go something like this (from
experience):

1) How many of our users will be affected? 2) How much harder (i.e. how much
longer) will it be to do it right? 3) Don't we depend on JS to inject ads
anyway? Ads are the whole reason anybody's paying for this...

When you truthfully answer #1, if #2 is more than about 5 minutes, nobody's
going to budget for it.

Overall, the hash-as-URL argument is hampered by the fact that Gawker is a
prime example of going single page just because you can. Other than fancy
page->page transitions, I don't see what their new setup buys them.

------
evandavid
For the time being, I will personally continue to build #!-only websites,
designed exclusively for javascript enabled browsers. Maintaining two versions
(along the guidelines of progressive enhancement) is just too much work
(maintaining and testing html view templates as well as jQuery or moustache
templates) considering that so few people lack javascript. I wouldn't let a
release go live without running a selenium suite across it in any case. My
perspective would be different, I imagine, if I worked on a large team that
could 'afford' to take the progressive enhancement route.

~~~
afhof
I take almost the polar opposite approach to you, always providing a safe
fallback to plain ol' HTML. I feel its a defensive style and doesn't provide a
single point of failure. I run Noscript since it makes most pages load much
faster. No offense, but I don't want to run your code, I'd rather read your
content.

~~~
evandavid
Fair. Would you feel the same way about a web application, as opposed to a
content-heavy site?

~~~
polynomial
Are there still content heavy sites? Not to be facetious here but it seems
user demand is aligned with smaller and smaller, more and more active bits of
content served by web applications. At some point you may have a _lot_ of
content, howev it's not so much heavy as it is highly interactive.

------
colanderman
Proposal: extend Transfer-Encoding to allow gzip encoding of multiple
responses in a persistent connection as if they were a single stream. This
way, a browser which expects to request multiple pages from a site can keep
the connection open, and the repeated content on each page will be gzipped
into oblivion.

The problems I see is that this would require both server and browser support,
and that leaving persistent connections open for minutes could be problematic.

~~~
metageek
Doesn't SSL do compression? (Most good encryption systems do, because
compression strips out the redundant data that codebreakers need.) If so, you
should be able to do persistent connections over HTTPS, and get the whole
stream compressed.

------
waqf
<http://news.ycombinator.com/item?id=2195280>

~~~
Terretta
Chuckle ... Clean URL blogger doesn't fixup his own URLs!

------
dennisgorelik
It looks like URL of that article is case-insensitive and page does not
specify canonical URL.

Both:

[http://www.isolani.co.uk/blog/javascript/BreakingTheWebWithH...](http://www.isolani.co.uk/blog/javascript/BreakingTheWebWithHashBangs)

and:

[http://www.isolani.co.uk/blog/javascript/breakingthewebwithh...](http://www.isolani.co.uk/blog/javascript/breakingthewebwithhashbangs)

render the same content, and <link rel="canonical"> does not exist in source
code of that page.

------
billswift
Hash bangs obviously aren't the only way to break web pages; has anyone else
noticed that the current Google homepage has broken the keyboard shortcuts, at
least in Firefox? You can't (or at least I can't) access the menu with the Alt
key now.

~~~
metageek
WFM. (Firefox, 64-bit Linux nightly build.)

------
carbonx
Did they do any sort of beta testing on this before they rolled it out?

------
nathansobo
Please. I for one am using the fragment hack to build a richer user experience
on a widely available platform. The interactions I am building wouldn't be
possible without it (or the HTML 5 pushState replaceState equivalents).
Rendering my content on the client in JavaScript makes me a lot more
productive, and the interactions I facilitate on my site would be impossible
without it. The implementation choices of a single web site cannot "break the
web". I trust that the author of this post has a lot of experience and also
valuable things to say about building accessible sites, but accessibility and
graceful degradation aren't the only god in my pantheon.

------
eapen
Even worse, they dont appropriately use the canonical meta tag.

------
kehers
In the first place, y should a news publishing site even use hash-bang url? U
r not a web app built on ajax

------
MichaelApproved
> _Being dependent on perfect JavaScript_

You're almost always dependent on perfect code to keep your site running, be
it server side or client side. If code breaks on the server side you're just
as screwed.

~~~
shabda
Server side code runs on one machine. Client side needs to run on many
OS/Browser/Plugins combo.

