The origins of Stimulus

January 6, 2018

From the translator: David Heinemeyer Hansson wrote a small text about why he and his team Ruby on Rails developed their own Javascript framework. The original text is placed in the repository of the new project

We write a lot of Javascript in Basecamp, but we do not use it to create "JavaScript applications" in the modern sense. All of our applications render HTML on the server side, then we add Javascript impregnations to revive them.

This is the path of the majestic monolith. Basecamp runs on a variety of platforms, including native mobile applications, with a single set of controllers, views and models created under Ruby on Rails. Having a common interface that is updated from a single place is the key to making the small team work well, despite the many supported platforms.

This allows us to be productive, as in the good old days. A return to those days when a single programmer could provide considerable progress without getting stuck in the layers of abstractions of distributed systems. The time before everyone began to think that the holy grail is the limitation of the server side before just JSON production for Javascript applications on the client.

This does not mean that there is no sense in this approach for some people in some sort of " somewhere. But as a basic approach to many kinds of applications, and of course, such as Basecamp, it is generally a regression from the point of view of simplicity and productivity.

Also this does not mean that the distribution of one-page JavaScript applications did not bring any benefit. They brought speed, more dynamic interfaces and freedom from reloading the entire page.

We also wanted Basecamp such a feeling. To make it look as if we followed a herd feeling and rewritten everything with client rendering or switched to completely native mobile applications.

This desire led us to a double decision: Turbolinks and Stimulus.

Before I go to Stimulus, our humble JavaScript framework, let me briefly recount the purpose of Turbolinks.

Turbolinks comes from the so-called pjax, developed in GitHub. The basic idea remains the same. The reason that a full page reload seems slow is not that the browser is hard at processing HTML sent from the server. Browsers are really good and fast at it. The fact that usually HTML content is more similar to JSON is also not important (especially considering gzip). No, the main reason is that CSS and Javascript must be reinitialized and applied to the page again. Regardless of whether the files are cached. This can be slow if you have a decent CSS and JavaScript size.

To bypass this reinitialization, Turbolinks keeps an ongoing process, as well as one-page applications do this. But, basically, this process is invisible. It intercepts links and loads new pages on Ajax. The server still returns full HTML documents.

This strategy alone can make most of the application actions really fast (if the server is able to respond in 100-200ms, which is possible with caching). For Basecamp, this accelerated page transitions 3 times. This gives the application the very feeling of responsiveness and dynamism that was most of the arguments for single-page applications.

But Turbolinks is only half the story. Below the level of full page change are small updates within a single page. Showing and hiding items, copying to the clipboard, adding a new entry to the todo list and other interactions that we make in modern web applications

Before Stimulus Basecamp used a mixture of different styles and patterns to add these features . Part of the code was simple in jQuery, a similar part in volume was in vanilla JavaScript and a somewhat larger object-oriented system. All of them worked together through explicit processing of events, based on data-behavior attributes.

It was easy to add new code like this, but it was not an integrated solution and we had several parallel existing homemade styles and patterns.

Three main concepts in Stimulus

Stimulus wraps the best of these patterns in a modest little framework that revolves around the three basic concepts : controllers, actions, and targets.

It is designed to progressively improve the HTML for which it is intended. So you can take a simple template and see what behavior is affecting it. Here is an example:


You can read this and get a pretty good idea of ​​what's going on. Even without knowing anything about Stimulus and looking at the code of the controller itself. It's almost like a pseudocode. This is very different from reading a piece of HTML that has an external JavaScript file hanging event handlers here. It also provides the separation of entities lost in many modern JavaScript frameworks.

As you can see, Stimulus does not worry about creating HTML. Rather, it clings to the current HTML document. In most cases, HTML is rendered on the server either by loading the page (first visit) or through an Ajax request that changes the DOM.

Stimulus concentrates on manipulating an existing HTML document. Sometimes this means adding a CSS class that hides, animates, or highlights an item. Sometimes this means rearranging the elements in groups. Sometimes it means manipulating the element's content, for example, converting UTC-time, which is cached together with the content, to the local one, displayed to the user.

In these cases, you want Stimulus to create new DOM-elements, and you are definitely free doing so. Maybe in the future we will even add a little sugar to make it easier. But these are secondary scenarios.

How Stimulus differs from mainstream JavaScript frameworks

This makes Stimulus very different from most modern JavaScript frameworks. Almost all of them are focused on turning JSON into DOM elements through some sort of template language. Most use these frameworks to give birth to an empty page filled exclusively with elements created through JSON-to-template rendering.

Stimulus also differs in status issues. Most frameworks have ways to maintain state inside JavaScript objects, then to render HTML based on this state. Stimulus is the complete opposite. The state is stored in HTML, so controllers can be thrown out between pages, but they are reinitialized as soon as cached HTML reappears.

This is a significantly different paradigm. I'm sure a lot of experienced JavaScript developers who have worked with modern frameworks will be mocked. But no, leave me alone. If you are happy with the complexity and effort required to support the application in a whirlpool, say React + Redux, Turbolinks + Stimulus will not please you.

But on the other hand, if you have a feeling, a thing over which you work does not require such a level of sophistication and separation of applications that are implied in modern technologies, then you will most likely find salvation in our approach.

Stimulus and similar ideas from the real world

Basecamp we used this architecture on several versions of Basecamp and other Appendix for a few years. GitHub used a similar approach with a remarkable effect. It's not just an alternative to the mainstream understanding of what a modern web application looks like, but surprisingly competitive.

In fact, this is similar to the secret ingredient we had in Basecamp when we did Ruby on Rails. The feeling that modern popular approaches are excessively non-directional, so that we can do more with less effort.

Moreover, you do not even need to choose. Stimulus and Turbolinks work fine in conjunction with other heavier approaches. If 80% of your application does not fit into a complex installation, try our two-component assembly for this. Then deploy heavy equipment for that part of the application where you will really benefit from this.

In Basecamp we do use a few more complex approaches where there is a need. Our calendar functionality uses client rendering. Our text editor, Trix, is a fully assembled text handler that would not make sense as a bundle of Stimulus controllers.

This set of alternative frameworks about getting rid of weights as far as possible. To stay within the "request-response" paradigm for most interactions that work perfectly with this simple model. First of all, this is a set of tools for small teams that want to compete in coverage with large teams using more time-consuming, mainstream approaches.

Give it a chance!

Link to the GiHub project

Leave a Comment

Your email address will not be published.