Backbone.js Routing: pushState vs Hash – Decision Guide
Choose between Backbone.js pushState and hash routing by evaluating browser support, server rewrite needs, and SEO impact. Follow this guide to decide, compare options, and implement the right setup.
25 Jul 2025, 07:17 UTC

Decision: Which Routing Mode to Use
When building a Backbone.js single‑page application (SPA) you must decide between pushState (clean URLs) and hash routing. The choice hinges on a few concrete constraints: browser support, server rewrite capability, SEO requirements, and whether you already use hash links in your project.
Constraints to Consider
- Browser support – pushState is supported in IE10+ and all modern browsers. Older WebViews (Android 4.4) may need a fallback.
- Server rewrite – pushState requires the server to serve the SPA’s
index.htmlfor every route; otherwise a page refresh will hit a 404. - SEO – clean URLs without a hash are more indexable by search engines and easier to share.
- Existing hash links – if your app already uses
#fragments (e.g., for deep linking), switching to pushState may break legacy links.
Option Comparison
| Feature | pushState | Hash |
|---|---|---|
| URL appearance | /users/123 | /#/users/123 |
| Browser support | IE10+, all modern browsers | All browsers (even IE6) |
| Server requirement | Rewrite to index.html for all routes | None – static hosting works |
| SEO friendliness | High – crawlers see clean URLs | Low – many crawlers ignore # fragments |
| Back/forward handling | Native History API, full navigation stack | HashChange event, limited stack |
| Mobile support | Full support on iOS Safari, Chrome Android | Full support, but some old WebViews may be flaky |
| Legacy link migration | Requires redirect rules or client‑side handling | Already works with legacy links |
Trade‑Off Analysis
pushState gives you clean, bookmarkable URLs that search engines can index. It also lets you use the browser’s native navigation stack, making the back/forward buttons feel natural. The downside is the need for a server rewrite rule; a misconfigured rule will produce 404s on page refresh or deep linking. Additionally, if you need to support very old browsers (IE9, old Android WebViews), you must provide polyfills for the History API.
Hash routing is the simplest to deploy. It works on any static host without server changes and guarantees that navigation never fails due to a missing route on the server. The trade‑off is that URLs contain a # fragment, which can be confusing for users and is ignored by most search engines. It also limits the ability to perform server‑side rendering or meta‑tag injection for SEO.
Concrete Implementation
Router Setup
Define a router and start Backbone.History with the chosen mode. Only one router instance should call Backbone.history.start().
var AppRouter = Backbone.Router.extend({
routes: {
"": "home",
"users/:id": "showUser"
},
home: function() {
// render home view
},
showUser: function(id) {
// render user view
}
});
var appRouter = new AppRouter();
// Choose routing mode
Backbone.history.start({
pushState: true, // set to false for hash mode
root: '/app/', // optional base path
hashChange: false // disable hashChange when pushState is true
});
Server Rewrite (Nginx Example)
When using pushState you must rewrite all unknown paths to /app/index.html so that the SPA can handle the route client‑side.
location /app/ {
try_files $uri $uri/ /app/index.html;
}
For Apache use .htaccess with RewriteEngine On and a similar RewriteCond rule.
Validation Checklist
- Toggle
pushState:truein the router start options and reload the app. - Navigate to
/app/users/42usingrouter.navigate('users/42', {trigger:true}). - Refresh the page – the server must return
index.htmland the router should render the user view. - Test the back and forward buttons – they should correctly step through the navigation history.
- Share the deep link URL and open it in a fresh browser window; verify no 404s and correct view rendering.
- For hash mode, repeat the steps without the rewrite rule to confirm that navigation works even when the server returns a 404 for unknown paths.
Common Pitfalls & Mitigations
- Missing rewrite rule – results in 404 on refresh. Verify with browser dev tools Network tab.
- Multiple
Backbone.history.start()calls – causes duplicate event listeners. Ensure only one router starts history. - Legacy browsers without polyfills – pushState fails. Include
history.jsores5-shimfor IE9 support. - SEO with hash – search engines ignore fragments. Use a prerender service or switch to pushState if SEO is critical.
- Mixed mode usage – avoid enabling both
pushStateandhashChangesimultaneously; pick one strategy for consistency.
Summary
If your target browsers support the History API and you can configure server rewrites, pushState is the recommended routing mode for clean URLs and better SEO. Use hash routing only when you need maximum compatibility on static hosts or legacy browsers and can accept the SEO trade‑offs.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.