The Life‑Changing Magic of Ruby and Rails

A Brief Introduction to Hotwire

This post introduces Hotwire, the suite of front-end frameworks shipped with Rails 7. It starts with a brief overview of the existing approaches to building web applications, introduces Hotwire, and wraps up with a short description of the different sub-frameworks that make Hotwire. We’ll also see how these frameworks fit together to provide a cohesive solution for the front-end ecosystem.

Traditional Web Architecture

To understand Hotwire, we first need to know how a typical request-response cycle works when a browser requests a web page.

When you go to a website in the browser or click a link on a page, it makes a GET request to the server, which sends an HTML response to the requesting browser. The browser then parses the HTML text and displays the web page.

The advantage of this simple architecture is that most of the application logic stays on the back-end, where you’re free to choose any language you like, including JavaScript. When you need some client-side interactivity, you use some JavaScript to get the job done. The page loads faster, as the browser only renders an HTML response without loading and parsing big JavaScript files.

However, a disadvantage of traditional web applications is that the browser reloads the whole page when you click a link, throwing away the existing HTML. It also fetches the assets listed in the HTML, such as JavaScript, CSS, and images again.

Now, these assets are cached on the browser most of the time, which makes this process relatively fast, but the basic idea remains the same. The browser has to parse and interpret the whole HTML again. So the web application doesn’t get a native application-like feeling. It still feels like a website.

Single Page Applications

This was the original web architecture (that made the web popular and successful), and many web applications still work that way. However, a new category of web applications became popular in the last ten years, known as Single-Page Applications, or SPAs for short. These applications make heavy use of JavaScript, using frameworks like React, Vue, or Ember.

The original page that first loads contains all the JavaScript to make the application work, and it behaves like a desktop application. Hence these websites are called Single-Page Applications.

Instead of fetching an HTML response from the server, these JavaScript frameworks ask for the JSON data, interpreting and rendering the JSON on the front-end. The browser doesn’t have to reload the whole page; JavaScript does all the work.

An example is the Rails forum powered by Discourse, a Single Page Application. When you click on a message on the forum, the browser doesn’t reload the whole page, unlike a link on the MDN documentation page.

Single Page Applications get a lot of their speed and responsiveness from not constantly reloading the browser, tearing down the application process, only to reinitialize it on the very next page.

Disadvantages of SPA

SPAs have a few disadvantages, such as when you first load the application, it is slow, as you have to load a big JavaScript bundle. To solve that, you have to compress and link together all JavaScript using a bundling tool like Webpack, which is not easy.

Also, you might have to duplicate the view templates both on the front-end and back-end. Managing and sharing links also becomes tricky, as you are always on the same page. SPAs are also not very SEO - friendly. As Barry Adams explains in his post,

What happens when you use React without server-side rendering is that the crawler halts on the very first page because it can’t see any hyperlinks to follow. It sends the page to the indexer, which then has to render the page and extracts the hyperlinks, which will then be added to the crawler’s queue. Then the crawler will eventually crawl the next set of pages, and again will stop there because all the links are invisible until the JavaScript is rendered. So it has to wait for the indexer to come back with a new set of URLs to crawl. Etc.

It makes the crawl process incredibly slow and inefficient.

In my experience, most of these “modern” apps are fragile, poorly implemented, have terrible first-load times, don’t work well with the browser’s back and forward buttons, and cause a bad user experience.

To be fair, Single Page Applications do try to address these concerns using various techniques, but that’s a big topic in itself. Some SPAs are even a pleasure to use, especially if implemented well. A good example is Discourse.

To be honest, many web applications just don’t need the SPA technology, with big, honking JavaScript frameworks and specialized teams. They’d work just as well, if not better, using plain, boring, old web architecture. As Stefan Tilkov explains in his 2016 post Why I hate your Single Page App,

Maybe your single page app is different, but the ones that I know break most of my browser’s features, such as the back and forward buttons, page refresh, bookmarking, sending a link, or opening a link in a new window or tab. They offer no way to link to something that I look at. (Oh, I know there are exceptions to this rule, but they typically require effort — a lot more than many developers are prepared to invest). They are bloated and slow to load, even though the actual information they display and the interaction they offer is very simple.

After working with and using many poorly implemented SPAs, I couldn’t agree more. I was so frustrated with the front-end and the onslaught of JavaScript frameworks over the past decade, I almost gave up on JavaScript and tried to stick to the back-end until I came across Hotwire.

Introducing Hotwire

Hotwire stands for HTML over the wire. It is a collection of techniques that tries to get the best of both worlds, keeping the original, simple web architecture of sending HTML over the wire, while not losing the performance benefits of Single Page Applications.

Now I’ve been playing with Hotwire for the past few days, and working on a Hotwire application is just fun. There’s no complexity associated with setting up the framework like React or having to configure Webpack, which I never enjoyed.

You write Ruby and as little JavaScript as possible, and your application just works. It’s also much simpler and easier to reason about and understand the whole application instead of maintaining separate front-end and back-end teams.

Hotwire is not a single framework; it’s a suite of different frameworks.

  1. Turbo uses different techniques to reduce the amount of JavaScript most web applications have to write. This is the most important framework of Hotwire.
  2. Stimulus, a JavaScript framework when you absolutely need to use JavaScript.
  3. Strada (not yet released) works with native applications, making it easy to progressively level-up web interactions with native replacements.

Turbo uses the following techniques to provide a SPA-like experience, while still keeping the simplicity of traditional web applications, i.e. sending HTML over the wire. We will learn about them in the following posts in this series.

  1. Turbo Drive accelerates links and form submissions. It listens for link clicks or form submissions, performs them in the background, and updates the page without a full reload.
  2. Turbo Frames divides pages into independent contexts called frames (not iframe). Turbo captures link clicks and form submissions inside a frame, automatically updating the frame contents after receiving a response.
  3. Turbo Streams delivers page changes over WebSocket, SSE, or in response to form submissions using just HTML and a set of CRUD-like actions.

If all these different frameworks and techniques are already sounding confusing, don’t worry. You won’t be using all of them equally, all the time. Here’s a diagram that might help you understand how it all fits together.

Turbo makes the majority of Hotwire. When you need to work with some JavaScript, you use Stimulus, and you only need Strada when your application needs to have native apps on Android and iOS.

Inside Turbo, Turbo Drive will satisfy most of your needs of fast performance. When you need additional responsiveness, you use Turbo Frames, and finally, a few cases where you need to bring your application alive, such as sending live updates from the server, you will use Turbo Streams.

We will learn about all these techniques in future posts (as I learn them myself 😅 ). For now, I hope this brief introduction helped you get a big-picture overview of Hotwire and understand how different parts of it fit together to provide a cohesive solution for the front-end ecosystem.

Subscribe to Akshay's Blog

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe