documentcloud/backbone — Issue #803: PushState Router unnecessarily breaks hash fragment links
Author: micheljansen
Created: 2011-12-20 16:38:25+00:00
State: open

Although I understand the history behind the Backbone Router, and I am sure there are scenarios where it is desirable to automatically fall back to hash fragment based URLs when there is no HTML5 PushState support, the current implementation is unexpected and inconsistent with how a normal web app is supposed to behave.

I am using Backbone.js to progressively enhance a page. In its current form, everything is 100% functional without any JavaScript. The purpose of the Backbone Router in this is to reroute certain actions to AJAX requests rather than page transitions. I am fine with only targeting modern browsers with PushState support (old browsers will just load the page without AJAX, it's a mobile app anyway). However, there are several hash-based fragment links in the page.

A good example is a link to #top at the bottom of a list of search results. Without Backbone in charge of the browser history, this works fine, but as soon as we turn on the Backbone Router things fall apart in subtle ways. The link to top still works (not triggering a route called "top" or "#top" in the Router, by the way), and now the "http://my-path.tld/#top". If I refresh the page like this, the Router reinterprets this to "http://my-path.tld/top" (this time it *does* trigger a route called "top"), which brings the app in an inconsistent state. There is no http://my-path.tld/top/ so if the user refreshes the page, bookmarks this URL or sends it to a friend, it results in a 404 error.

I read the comments on https://github.com/documentcloud/backbone/issues/418 as a kind of "you're holding it wrong"-response. I do not believe this is the case. If the Backbone Router operates on real URLs, they should be consistent with the way they are supposed to work without JavaScript and as they are now they don't.

There are probably several solutions to this, but the easiest one would be to allow developers to opt in/out of PushState and hashchange separately and not redirect /#top to /top by default.