Every Web App is (at least) Two Applications
Yesterday I came across "Rails' Degenerate Front-End Support" taking Rails to task for slipping behind the state of the art when it comes to front-end dependency management. The pain is real, but the problem isn't that Rails does a bad job with front-end dependencies. The problem is that the front-end has no business living in a Rails app at all.
Web applications in 2005 were engines of request and response. You were always interacting with a snapshot of the data, never the data itself. In this era, it made perfect sense for the server to generate the HTML that landed in the browser. After all, browsers were terrible! IE7 had just come out, Firefox had only a tiny sliver of the market, and anything you could do to keep things server-side was a win.
Sure, AJAX existed and could be cajoled into helping out here and there. By and large, however, the server was running the show. What a difference a decade makes.
What has happened since 2005 came about so gradually that many haven't even realized it happened. Browsers got better. Not just a little better. Browsers got magnificently, insanely, unbelievably better. They became faster, they supported more standards and newer standards, they landed on whole new device categories without giving up (too much) ground. Even better, they started releasing much more frequently ensuring they would continue to get better. In the past decade, the browser has evolved from a document viewer that could be hacked into a basic application provider to a full-blown operating system in its own right.
Backbone, Mind Blown
It all started with Backbone, first of the mainstream modern JavaScript frameworks. Like Rails before it and with just around 1,000 lines of code, it had the audacity to challenge the whole way we built applications. Sure, I'd wired up some pretty complex jQuery code by 2010, even dabbled with real-time, but Backbone was the first library that shouted in your face "your front-end is an application." It showed us a map that showed just how far we had come since 2005, and gave us a glimpse of what was to come.
The seed of the idea had been planted. Your front-end is an application. It makes perfect sense and has now for some time. We test the limits. We move from pull to push. We build more and better interaction away from the request/response mindset. And our users love it. The web is more alive today than it's ever been.
So where does that leave Rails?
We're Gonna Need a Bigger Toolbox
Rails has an inherently monolithic mindset. It's a web app in a box. It's a fantastic framework for tying application code to a data store and preparing that data for rendering to the browser. It has thousands of libraries written by thousands of developers to do thousands of things extremely well. You can still build a great modern web application using Rails. You just can't build one only using Rails.
Yes, Rails has the asset pipeline. There are gems that let you use Bower, Angular, Ember, and everything else you might imagine inside your Rails app. But front-ends aren't kids anymore, and it's starting to get embarrassing when they're still living in their parents' basement.
By now, most Rails developers have picked one or more of the modern JS frameworks to use when building apps. Whether it's Backbone, Angular, Ember, or something else. It's not a change in tools that's needed, it's a change in perspective.
The back-end is for persisting and retrieving data. The front-end is for user interaction. And the two should not live in the same repo anymore.
A Modern Approach
I still love Ruby. JavaScript runs in the browser and has better conventions around concurrency, but if I have a choice of language I'm still picking Ruby. But today when I start building a new application, I make two folders: myapp-api and myapp-web.
In my front-end app, I use a variety of tools suited to the purpose like Yeoman, Broccoli, Grunt, or even just bare HTML. In my back-end app, I create a JSON interface to my application logic and data stores using Grape or Sinatra. I deploy the two applications to two separate servers: api.myapp.com for the back-end, and myapp.com or www.myapp.com for the front-end.
The result is a change both much smaller and much bigger than you'd expect. Before I had completely cut the cord between front and back-end, I was already effectively building two separate applications. I just had the artificial constraint that they needed to live in the same repository for some reason.
After the separation, I find that my architecture is much cleaner. I can focus on a single purpose. When I'm working on the back-end, I worry only about a clear and logical representation of application data. When I'm working on the front-end, my only concern is user experience. More than that, it feels right. It feels like I'm building things correctly.
I'm not saying Rails is dead. While I've moved on to lighter frameworks (admittedly, one I designed myself), Rails is still an extremely capable way to implement your web app's back-end. I just think we should stop pretending that there can or should be a single framework that encompasses all the needs of a modern web application.
Keeping front-end and back-end tightly coupled is condemning them to run a three-legged race, awkwardly tied together when both would benefit from separation. Cut the tie. You'll be glad you did.
Looking for separation advice? Check out StaticApps.org or feel free to email me directly with any questions or potential worries. I've been down this road for a while and might be able to help.
And if you're looking for a new home for that recently liberated front-end, well, we built Divshot for the express purpose of being a great one.