If you're building web applications in the Ruby on Rails ecosystem, you must have heard about Hotwire, the suite of front-end frameworks that were shipped with Rails 7.
All the new terms associated with Hotwire, such as Turbo, Drive, Frames, Stimulus, Strada, etc. can be confusing to understand at first. This post provides a brief introduction to Hotwire and its component frameworks.
We'll start with a brief overview of the existing approaches to building web applications and the problems associated with them. Then I'll introduce Hotwire, and wrap up with a short description of the different sub-frameworks that make Hotwire.
We’ll also learn how these frameworks fit together to provide a cohesive solution for the front-end ecosystem, not only for Ruby on Rails, but for any back-end framework, such as Laravel.
Here're the topics we'll cover in this article.
- Traditional Web Architecture
- Single-Page Applications (SPAs)
- Disadvantages of SPAs
- A Brief Introduction to Hotwire
Let's get started.
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 and displays the web page.
The advantage of this simple architecture is that most of the application logic stays on the backend, where you’re free to choose any language you like, such as Ruby, PHP, or even JavaScript.
When you need some client-side interactivity, you sprinkle some JavaScript (or use JQuery) to get the job done. The pages load much faster, as the browser only has to render an HTML response without loading and parsing big JavaScript frameworks.
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, even if they haven't changed.
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.
This was the original web architecture (that made the web popular and successful), and many web applications still work that way. However, with advances in browsers, a new category of web applications became popular in the last ten years, known as Single-Page Applications, or SPAs for short.
Single-Page Applications
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.
These are web applications making heavy use of JavaScript, using frameworks like React, Vue, or Ember. The initial page 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 frontend. The browser doesn’t have to reload the whole page; JavaScript does most of the work.
A good example of a single-page application is the Rails forum powered by Discourse. When you click on a message on the forum, the browser doesn’t reload the whole page, unlike a link on the MDN documentation, which uses the traditional web architecture. Notice how the full page reloads whenever you click any links on MDN, but not on the Rails forum.
Disadvantages of SPAs
Single-Page Apps 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 a simple process.
Also, you might have to duplicate the view templates both on the frontend and backend. 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,
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" SPA apps (and I mean most business applications, not the slick demos you see on the React or Next.js websites) are fragile, poorly implemented, have bad first-load times, don’t work well with the browser’s back and forward buttons, and cause a bad user experience.
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.
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. The best example of a flawlessly executed single-page application is Ghost, the blogging platform I use to write and publish this blog.
However, after working with and using many poorly implemented SPAs, I couldn’t agree more with Stefan. I was so frustrated with the frontend and the onslaught of JavaScript frameworks over the past decade, I almost gave up on JavaScript and tried to stick to the backend, until I came across Hotwire.
A Brief Introduction to 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.
Hotwire is not a single framework; it’s a suite of different frameworks that allow you to send HTML responses over the wire.
- Turbo uses different techniques to reduce the amount of JavaScript most web applications have to write. Turbo lets you send HTML from the server (both in response to user interaction, such as clicking links or submitting forms, or via WebSockets) which updates parts of the page dynamically, without any custom JavaScript.
- Stimulus is a JavaScript framework when you absolutely need to use (or sprinkle, as DHH would say) some JavaScript. You use Stimulus where you need client-side interactivity. Learn how Stimulus works.
- Strada (not yet released) works with native applications, making it easy to progressively level-up web interactions with native replacements. Hopefully, 37Signals will release Strada in 2023.
Turbo
Turbo is the most important framework in Hotwire. It uses multiple techniques to provide a SPA-like experience, while still keeping the simplicity of traditional web applications, i.e. sending HTML over the wire.
- 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. Learn how Turbo Drive works.
- Turbo Frames divides pages into independent contexts called frames (not iframes). Turbo captures link clicks and form submissions inside a frame, automatically updating the frame contents after receiving a response. Learn how Turbo Frames work.
- 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 for fast performance. When you need additional responsiveness, you use Turbo Frames, and finally, in a few cases where you need to bring your application alive, such as sending live updates from the server, you will use Turbo Streams.
This is just a very high-level overview of these components. If you are interested in learning more, I have a detailed tutorial on building a to-do list with Hotwire that shows how to build a single-page web application using Hotwire.
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.
At my day job, I've been working on a web application built on Hotwire (that was migrated from React) for over a year, and the development experience is just amazing. You write Ruby (or whichever backend language you love) and as little JavaScript as possible, and your application just works.
The architecture of Hotwired applications is much easier to understand and reason about, as they're just traditional web applications. They also feel as snappy as a SPA, as we aren't reloading the whole page on each request. Maintaining them is much simpler, and you don't have to use separate frontend and backend teams.
I hope you found this article useful and that you learned something new.
If you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I look forward to hearing from you.
Please subscribe to my blog if you'd like to receive future articles directly in your email. If you're already a subscriber, thank you.