I've set up a super simple Backbone app with just a router and two views to try and nail down the correct way to handle routing with no hashbangs.
var Router = Backbone.Router.extend({
routes: {
'': 'index',
'episodes': 'episodes'
},
index: function () {
var view = new IndexView();
view.render();
},
episodes: function () {
var view = new EpisodesView();
view.render();
}
});
var IndexView = Backbone.View.extend({
el: $('#primary'),
render: function () {
console.log('index view');
}
});
var EpisodesView = Backbone.View.extend({
el: $('#primary'),
render: function () {
console.log('episodes view');
}
});
var router = new Router;
Backbone.history.start({pushState: true});
I realize that the history
object allows forward and backward navigation between pages, which is great. However, the way it's actually implemented seems a little messed up to me.
For instance, I created a simple MAMP server to serve an index.html
file and the JS file. Navigating to http://backbone:8888/
, the console logs index view
like I'm telling it to. However, navigating to http://backbone:8888/episodes
(by typing it into the address bar) returns a 404. BUT, if I navigate to http://backbone:8888/#episodes
, the URL redirects to http://backbone:8888/episodes
(without the hashbang) and I get episodes view
logged to the console, which obviously means it's hitting that EpisodesView
view.
From here, I can go back and forth between the index and episodes views. (back hits /, forward hits /episodes). That's all fine and dandy until I hit refresh while on /episodes
again. 404...
So my question is this: how can Backbone be set up to handle URLs without relying on hashbangs? Everything I've found on the topic says "oh just pushState
!". Well, I'm using pushState
and, like I described above, you can't hit a URL like /episodes
directly without getting a 404.
When you use push state, pages are served from the back end, which means that you have to define a corresponding route in your back end that corresponds to a front end route.
If the back end doesn't find the requested route, then it will deliver a 404 message, because it won't know what to serve. In your case, the episodes view gets triggered at the front end level, but the browser doesn't have a DOM to render the view when the page gets refreshed because nothing was served.
By default, the route http://backbone:8888/
will serve the index file because this is how the webserver is configured.
I'm not sure what back end technology you are using, but for serving a file from http://backbone:8888/episodes
, just make sure that your back end has a router set up that serves the requested route and it should work.