For the past 3 years I had been working on a Rails app with an Angularjs 1.5 front-end (SPA); I didn’t love it. It was much more complex than it needed to be. Our front-end permission management was CanCan implementd for the front-end that would interpret our backend’s CanCan permission object passed to it as JSON. The routing rules used a lot of regular expressions. The pages had deeply nested Angular controllers. The Angular templates were dozens and dozens of Rails view partials buried deep inside various directories. I would often fantasize about deleting the whole thing and replacing it with straightforward HTML. Most of the functionality would have been the same.
I switched jobs a few months ago. The team I joined is replacing an application that is a mixture of jQuery, Angular, React, Bootstrap, and Foundation. It uses the Rails asset pipeline together with Webpack. It is a mess. The JavaScript feels like a cancer that has spread everywhere.
For the new application we decided to use Stimulus. It is endorsed by the Rails team and its promise to be “a modest JavaScript framework for the HTML you already have” felt like a breath of fresh air.
However, after using Stimulus for a couple of months I realized that it wasn’t for me for a variety of reasons, including:
- There is nothing in the Stimulus documentation about how to test it. I tried to work out some strategies on my own, but nothing was particularly satisfying.
- There is not a lot of documentation in general. For example, it took me a fair
amount of searching to discover that they use “
--
” in their naming for subdirectories. I don’t think it is in the documentation still. - Putting all of your state in the DOM is tricky. If you have anything that modifies the DOM (for example, we had something that toggled between an “edit” and “view” mode) you could clobber your state; taking state out of the DOM is one of early arguments for Backbone.
- There is no easy way to coordinate or message between controllers, especially nested ones. One of React’s key features is that components can easily pass information to their child components.
- Stimulus disconnects functions from their parameters. You call a function and then it
has to search for the applicable
data-
attribute in the DOM. - Their naming scheme is cumbersome, e.g.
data-controller="using-a--sub-directory" data-target="some--nested--target-has-a.function"
. Everything is location-in-your-code-file-structure based. - It was hard for me to get reusable pieces of code. Because nesting controllers seemed to make things complex, I stopped trying to make them work together and I just started making a controller per page.
- It doesn’t try to work with the larger JavaScript ecosystem
A lot of my frustrations with Stimulus stem, I think, from my differences from how David Heinemeier Hansson works. I’ve listened to several of his interviews, including recent ones about his Hotwire approach. For example:
- He doesn’t like JavaScript and tries to avoid it when he can.
- He has a front-end team who can write custom code for him.
- He is focused on Basecamp and Hey
In contrast:
- I don’t love JavaScript, but I can appreciate its usefulness and I try to respect it for what it is.
- I am a full-stack developer, which means I have to live with the JavaScript I write and I often need to use JavaScript libraries.
- I work on products that don’t necessarily have the same needs as Basecamp or Hey
About the time I was hitting peak frustration with Stimulus, Vue released version 3. I’ve found that it addresses my frustrations well:
- There are official testing libraries for Vue and with a lot of documentation.
- Vue has the most and the most thorough documentation of any JavaScript framework I’ve seen.
- Vue has several strategies for state management and you don’t have to put state in the DOM.
- Vue has support for passing data between components as well as support for emitting and listening to events.
- Vue makes it clear what parameters are being passed to functions.
- Vue has a lot of naming guidelings, but what you name things is much more flexible.
- Vue encourages code reuse through “composables” (very much like React’s hooks) and components.
- Vue tries work with the JavaScript ecosystem.
The part of Vue that I like the best is that it is a “progressive” framework. That is, I can use it for “sprinkles” at one end or a full single page application at the other. I can write HTML first and then use it for “the HTML I already have.”