Rails and JavaScript, Part 4: The Future?
It’s hard to predict…
Previously on Locally Sourced: Well, we’ve been talking about the history of Rails and JavaScript: part 1, part 2, and part 3, and we’ve finally caught up to the present time, so I guess it’s time to talk about the future. Also, my Rails and JavaScript book is still on sale. You might want to buy it.
This is all a little speculative, based on the are changes that have been made to Turbolinks and Stimulus that are clearly in use in Hey.com, and are scheduled to be release (probably), but have not been released. Hey.com does not obfuscate its JavaScript source, so you can go in and browse it — I am indebted to this series by Matouš Borák for a good dive into the public parts of the Hey source.
The New Rails Way
It seems like the New Rails Way adds the following pieces, at least:
- A way to do a Turbolinks page update from a form submission.
- A way to have a page automatically make a server request on load without any custom JavaScript.
- At least one and possibly two ways to update the page DOM with HTML from the server without writing any custom JavaScript.
- Very increased use of CSS.
- A statement of purpose.
Let me start at the end, this was something DHH said on Twitter a month or so ago…
The fundamental insight is that we can avoid 95% of all app-specific JavaScript by building better, more flexible framework solutions. All new app-specific JS now has to answer: Why? Why not CSS? Why not [new approaches]? Result: Very little app-specific JS!
— DHH (@dhh) May 28, 2020
The New Rails Way of front-end development, then, is to assume that the overwhelming majority of user actions can can be handled as some composition of simple CSS changes to one or more DOM elements, or the replacement of one or more DOM elements with HTML from a server request. In the rare case where that’s not enough, the idea is to augment with general DOM manipulation logic, and leave business logic on the server side. (The dev.to series walks through how this plays out with the way that Hey.com handles the transition when you mark an email as seen…) The advantage here is that the more functionality that you can implement with very simple CSS or HTML changes, the less code you write, and the more focus you can put on the parts of your app that are legitimately complex.
With that, I think I have three points:
This really is full-circle.
The Rails 1.0 front-end model was a helper that you wrote server-side in ERb that triggered the replacement of parts of the DOM with new HTML from the server based on a user action.
The Rails 6.1 front-end model, after some twists and turns, is made up largely of data attributes that you write server-side in the ERb markup and which largely trigger the replacement of parts of the DOM with new HTML from the server based on a user action.
There does seem to be a slight similarity.
Snark aside, the new model has a lot going for it relative to the original. It’s far more flexible in terms of what you can do on the page without writing more JavaScript. It’s also backed by a lot of JavaScript framework code rather than server-side Ruby code, and is easier to integrate with the larger JavaScript ecosystem. The new model is much easier to augment with different client-side interactions, and it encourages you to write more general framework-like code for even your somewhat custom logic.
Even when I’ve used Stimulus recently, I didn’t use HTML as the main server API response, but I think with the new tools, I could have cleaned up some logic from my most recent Stimulus project.
It fits Rails architecture
At least, potentially.
Rails is structured mostly in terms of resources, where a resource is often-but-not-always tied to a database table, but is always something that can meaningfully reply to the seven basic CRUD actions for a Rails controller. Rails routing and general structure make resources useful enough that it makes sense to split your application into resources, even if that is not completely natural. (For example, rather than having a UserContoller#search
action, I might have a UserSearchController#show
action, setting up a new resource with a common action rather than putting a custom action in the existing resource).
Anyway, client-side apps in the React/Vue/Angular family aren’t structured that way, those components tend to be smaller and tied to the page layout rather than to the controller action structure.
But in the Nouveaux Turbolinks world it looks like it is at least possible to structure your front-end interactions such that they align with Rails resources – it looks like you’d often be making, for example, show calls to refresh part of a page. I think this might make the logic split between client-side and server-side structures easier to manage.
CSS is a force multiplier
One thing that struck me as I was going back over old Rails tools, was how much of the visual effects that used to be done in JavaScript are now possible and much easier in CSS. And looking at how Hey.com uses CSS tied to a data attribute to manage some of the layout made it clear to me that improvements in CSS have made the HTML over the wire approach much more powerful than it was before.
With CSS animations, layout, graphics, before and after elements and the like, you can offload onto the browser’s rendering engine all kinds of visual effects that you would otherwise have to write code for. This feels like a huge win to me, but it’s basically what CSS is commonly used for.
Taking it even a step further, it looks like Hey is, in effect, using CSS to handle some of the responsive view render changes that we would normally expect something like the React engine to handle. I’m not sure how far to take this – there are clearly some data things that CSS can’t handle, but I look at how Hey does the “Previously Seen” header, which involves a :before pseudo-class tied to tied to the first element in a list that has a particular data attribute, which means that changing that data attribute automatically moves the the header, and I think there’s lot of power available there at relatively low cost.
This is still not public yet, maybe some of it won’t be public, or maybe it’ll be harder to use than I think. But right now, it looks like a pretty great way to get the 80/20 rule for front-end coding with 80% of the power for 20% of the cost.
What do you think? Does this way of doing front-end apps interest you?
Next time: Back to Agile, we talk about teams and metrics.