minisaurus
minisaurus

Reputation: 1196

Configure node express for Backbone SPA with pushState

My express app has a rest server and a SPA using Backbone. All works fine using # history, i.e.

Backbone.history.start();

If I do:

Backbone.history.start({ pushState: true });

the Backbone router ceases to work - a route that Backbone handles fine (e.g. #route) gets sent to Express when it becomes /route. Express errors with:

Cannot GET /route

I tried:

Backbone.history.start({ pushState: true, root '/' });

but no difference.

I also tried:

app.use('/*', function ...

in Express - no difference.

express server.js:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res){
  res.render('index.ejs');
});

var rest = require('./routes/rest');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use('/rest', rest);

app.listen(3000);

The Backbone router (slimmed a bit):

const Router = Backbone.Router.extend({
  routes: {
    '': Controllers.home,
    'admin(/:table)(/:id)': Controllers.admin,
    'master(/:table)(/:id)': Controllers.master
  }
});
Backbone.history.start({ pushState: true });

I don't need any SEO, I'd just like to get shot of those '#' in the app's routes.

Upvotes: 1

Views: 193

Answers (1)

François Richard
François Richard

Reputation: 7045

I think the router is working fine. It's "not working" when you are calling directly /index.html/someroute from the browser instead of the app.

To handle this you have to catch it in express

app.get('*', function...)

should work.

Be sure to declare the other route first (like /rest) otherwise it will be caught by '*' before reaching '/rest'. This is due to the middleware pattern express is using (just a reminder you may already know this).

Hope it helps!

Upvotes: 2

Related Questions