Impress: Express in the browser

A couple of weeks ago a friend of mine and I were discussing the potential for sharing code between the front- and back-end when using Node.js. With the explosion in popularity both of Node and front-end Javascript frameworks, code-sharing across environments seems like a natural course of action to maximize developer happiness.

Since we both use Express frequently, we started kicking around the possibility of using it in the browser - capturing all the actions that would normally lead to an HTTP request (clicks on links, form submissions) capturing them, and processing them the same way that Express does.

Last weekend, I threw together Impress, a front-end Javascript framework that has (very) stripped down Express functionality [1]. With the help of my Node.js-style module-loading library Joules, you can build what looks like an Express application entirely on the front-end.

In building that, I learned a lot about why this was a bad idea:

  • Rendering an entire response (the way that res.render or res.send does) doesn’t make sense in the browser - you rarely want to refresh the entire screen if you don’t have to.
  • URL’s are only useful as a way to tie together the front-end and back-end. If you’re dealing with just the front-end, URL’s are a very indirect way to define events (e.g. clicks, form submissions) and event handlers (e.g. app.get).
  • In order to really share code between the front- and back-end, you would have to maintain a different set of API endpoints for database access that both your front- and back-end talk to. CouchDB would be a good fit for this, but if you’re using something like MongoDB/Mongoose, you’re looking at defining an entirely separate set of routes to handle - not exactly minimizing work.

In discovering why Express was a bad fit for the front-end, I began to wonder if it’s really the best fit for the server. It feels right, but I suspect that’s mostly because it borrows paradigms from popular Ruby web frameworks (Sinatra and Rails).

Javascript and Node.js are heavily event-driven, so I’m beginning to think that it might be better to design the entire web server around event handling. In that case, a URL would just be one particular type of event. That mindset makes sense - when a user clicks a button it’s because they want to do something. Whether we listen for that event on the front-end (button.on("click", handleButtonClick)) or the back-end (app.get('/button/link/location', handleButtonClick)) we’re really just interpreting and acting on user intent.

If you know of any frameworks that work that way, let me know on Twitter.

1 - The biggest missing piece is the lack of support for middleware, which is probably the biggest benefit of using something like Express/Connect