Rails and JavaScript: Part Three
Previously on Locally Sourced: Rails came out and let people do Ajax, when Ajax was a thing. Then Ajax was less of a thing and Rails let people write CoffeeScript, and use Sprockets. Also, I wrote a book on Modern Front-End Programming with Rails, which is relevant to this edition.
The Rails 5 and 6 releases have had a few big JavaScript components, with one more presumably imminent. With Rails API and Webpacker, Rails made a big move toward allowing better interoperability with the JavaScript ecosystem. But with Stimulus and the upcoming new Turbolinks, the Rails team also presents a clear alternative to single page apps.
Rails API
Rails 5.0 introduced Rails API and ActionCable. I don't have much to say about ActionCable except that it seems to basically work and using it is not my favorite developer experience. Rails API is a minimal version of Rails with no view code designed as a server-side for single page apps and mobile apps. It has a bit of a history in that it was an actual fork of Rails for a while before being incorporated back into the main repo. If I'm remembering correctly, the API version was added into Rails in the 3.x or 4.x time frame and then removed by DHH, which triggered the fork, and then the re-incorporation. I've never used it in a production project, but I think Rails is better served by having it as part of the main project rather than a fork.
Webpacker
Webpacker was introduced as a separate project in conjunction with Rails 5.1 as the new way of packaging JavaScript assets from Rails. On the JavaScript side, webpack had emerged as the leading -- but by no means the only -- library for packaging and managing assets for the browser's consumption. Though powerful and flexible, webpack is a little daunting and hard to manage as the plugins add up. Webpacker, like many Rails-y things, attempts to create a reasonable configuration and sensible defaults for using webpack.
I basically like Webpacker, but it's a little too fickle for it to be in my "I love it, it just works" category.
The main upsides to Webpacker:
Reasonably low bar to get started on in the simple case.
Allows for easy installation of many different popular JavaScript tools.
Gives access to the JavaScript ecosystem in a more direct way than Sprockets does. Presumably this makes it more future-proof, at least until the JavaScript community finds an even newer and shinier tool sometime next week.
The main downsides to Webpacker:
Especially early on, delivering CSS and static assets via Webpacker was complicated, leading many teams (including Basecamp itself) to use both Webpacker and Sprockets. This seems objectively over-complicated.
I worry that, like Sprockets, it's a little under staffed relative to webpack and will continually be playing catch-up to new versions.
It's a pretty leaky abstraction, and eventually, you do need to learn some webpack if you want to do anything complicated.
Early on, I predicted -- incorrectly -- that there would be a flurry of Ruby projects adding more Ruby DSL syntax on top of Webpacker configuration to make config changes even easier on the Rails side. I haven't seen this, and I wonder if the reason is that Webpacker as-is is enough if you were using the Basecamp patterns, and if you aren't, you'd just as soon clean up your configuration in actual JavaScript.
Stimulus
Cards on the table here, I really, really like Stimulus. I've been successful with it, I like the philosophy behind it, and I think it's admirably not-complex and has a very strong "it just works" vibe. I've thrown some weird dynamic stuff at it, and Stimulus handled it just fine.
I first heard about Stimulus at RailsConf 2017, when -- there's no non-obnoxious way to say this, although I suppose I could not mention it at all -- DHH was casually in the exhibit hall talking with Justin Searls about their different opinions on dealing with JavaScript, I happened to be around to listen and sort of participate. Anyway, DHH said that Basecamp was starting to extract their common JavaScript interaction patterns to a framework and that they would eventually release it as its own thing and that it was going to be great. Which turned out to be Stimulus.
If you just want a very simple JavaScript action leading to something happening on the page, Stimulus lets you do so with an extremely small amount of code. Stimulus is designed for these small bits of interaction, and also to make it easy to compose lots of small bits of interaction so as to build more complicated interactions, still with not much code. It lends itself to dynamic logic and mini-frameworks on top of it, because it's easy to use the data attributes of the mark up to allow for runtime logic.
One thing I like about Stimulus is that it breaks with the "unobtrusive" style by putting a lot of information directly in HTML as data
attributes. This solves a classic problem in the jQuery spaghetti style of JavaScript programming, which was figuring out which elements in the HTML were actually important for JavaScript purposes such that you could actually find the related code, and also so that you didn't accidentally change some DOM ID and break all the code. The SPA frameworks all solve this problem by essentially pulling the markup into the code, either in JSX or in Vue-templates or whatever. Starting from HTML and adding extra attributes feels less complicated to me.
Stimulus encourages a much different design structure than React. Although you can build reactive behavior and external state into Stimulus, you'll reach a point where you are building a half-assed version of React and it's going to feel awkward. Stimulus is usually better served keeping state in HTML data
and handling reactive changes differently (with CSS, or with going back to the server for more HTML).
Honestly, the whole JS book would be Stimulus, except that Stimulus isn't that big, and also that adding React more or less opens the book to about 10 times the potential audience. I have nothing against React -- I quite like it in small doses, though I think a lot of SPA React code is more complicated than it needs to be. If the book gets a lot of people to read it because of React and a bunch of them discover how easy Stimulus is, I'd be thrilled.
Which brings us up-to-date, with new tools alluded to but not released, next time, I'll talk about them a little bit.
Dynamic Ruby is brought to you by Noel Rappin.
Comments and archive at noelrappin.com, or contact me at noelrap@ruby.social on Mastodon or @noelrappin.com on Bluesky.
To support this newsletter, subscribe by following one of these two links: