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
orres.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