00:00:09.440
Hello, everyone! Thank you for having me. Today, I’m going to talk about Hotwire and ViewComponent.
00:00:14.480
These tools can be used to build a modern monolithic application in Ruby on Rails. Let me share a few words about myself.
00:00:22.160
My name is Yaroslav Shmarov, and I’m from Ukraine. I speak several languages, and you might have come across me on Twitter or seen my YouTube channel, Super Rails.
00:00:28.840
I have quite a few videos about Hotwire there, along with my blog, which attracts around 200 Ruby on Rails developers daily.
00:00:33.920
Additionally, I might have some content on Udemy. I work at a French startup called Bearer.
00:00:40.640
Initially, I was hired for a very specific job, to be a frontend developer. My focus has been on Tailwind, Stimulus, and Hotwire.
00:00:53.039
The company is a few years old, but back in 2020, they decided to pivot. Previously, they were using Rails with GraphQL and React, but during the pivot, they concluded that this stack wasn't necessary.
00:01:07.680
As they were rewriting the application, Hotwire was released, so they thought, 'Why not give it a shot?' They decided to try Hotwire and ViewComponent instead of maintaining a separate frontend and backend.
00:01:15.119
Before I continue, I'd like to share a couple of thoughts on React versus Hotwire. I believe Hotwire is particularly excellent when you're in the early stages, especially if there aren't many developers. When it comes to building a React application, I find it appropriate only when an API is needed to support a mobile application.
00:01:39.360
Hotwire allows you to quickly create desktop experiences. In my opinion, React is better suited for B2C products where most users access services from their phones, while web applications are generally more tailored for B2B environments, where people use laptops at work. It's not fair to compare Hotwire and React as if one is better than the other; they are different tools for different jobs.
00:02:30.080
For instance, Hotwire executes server-side rendering, which means you can't build certain applications like a mirror clone or a tool as complex as Figma, or a good Notion clone. However, you can still build many useful applications like a Jira-like system or any kind of information management system.
00:03:07.440
You could construct components that are updated separately from each other, and you can create platforms like Twitch, Amazon, or Salesforce. Hotwire is indeed capable of supporting many different functionalities.
00:03:19.040
Going back to the company I work for and the technology stack we currently use: on the frontend, we have Hotwire, ViewComponent, Tailwind, and we recently transitioned from Webpacker to CSS and JS bundling.
00:03:43.920
This transition has been one of my favorite pull requests merged in the past year. The builder time has dramatically decreased, from around 40 seconds to something like five seconds, which has significantly improved the developer experience.
00:04:10.560
However, it wasn’t an easy migration; it required some effort to figure things out, but ultimately it was 100% worth it.
00:04:22.960
Now talking about structuring the front end in Rails, you'll encounter helpers, decorators, partials, and templates. I've observed that there can be issues with helpers and decorators; for instance, decorators are object-specific, while helpers are global.
00:04:49.759
You can define anything globally in the application helper or an events helper, allowing you to access it anywhere. If you're not careful, this might result in conflicts, whereas decorators necessitate creating an object, which does not wholly address the need for having components in your frontend.
00:05:08.560
The collaboration between the design team and the frontend team is also crucial. The design team can provide Figma designs, and I'll share a screenshot of our design team at Bearer who created various badge designs.
00:05:30.240
You can see there are many variants of badges, and implementing these designs in real templates can be tricky, but ViewComponent makes it quite manageable.
00:05:43.360
For instance, here is how we implemented the badges, allowing designers to visualize the actual achieved design on our staging environment. The ViewComponent file describes the various sizes and variants of the badge component and incorporates validations.
00:06:07.199
Additionally, we have a CSS file that styles these badges based on their variants, and the HTML file for all variants is succinct, comprising around only 10 lines.
00:06:30.560
A noteworthy finding in using ViewComponent is that while you might have a fixed set of variants (like black, green, or blue), you'll often want to add custom CSS at some point. Instead of creating additional variants, you can append CSS classes to your existing classes to create customized styles.
00:07:08.319
Every component can have default data attributes from a Stimulus controller, which you can extend to include additional attributes. This flexibility allows you to avoid rewriting components or creating duplicates, enhancing the adaptability of ViewComponents.
00:07:38.360
Moreover, while some components might be object-specific, there are also general ViewComponents where you can pass various parameters like color or size. For example, in an inventory component, I may pass a specific object to render different aspects of that object based on the data provided. The Ruby file associated with the component encapsulates the rendering logic, making it more manageable.
00:08:30.080
You can also nest multiple components within a single ViewComponent. For instance, I can have a component where I pass a `color` parameter, and it can take on various labels or records, which results in dynamically generated content in the HTML file.
00:08:55.600
Regarding CSS, whether to create separate CSS files for each ViewComponent depends on the case at hand. You can choose to keep all CSS in a single application stylesheet, but if a component has extensive styles, it could make sense to have its dedicated CSS file for better organization.
00:09:01.279
Creating form inputs, however, often poses more of a challenge when building frontend components. I've encountered situations where I needed to construct a custom dropdown or select component with options, including the ability to search.
00:09:20.480
It was a considerable task to ensure these form inputs worked seamlessly in conjunction with the hidden form they are connected to.
00:09:34.800
It’s essential to note that you don’t have to completely abandon templates or partials in favor of ViewComponent. How to structure your components significantly depends on the specific use case.
00:09:54.800
For example, a regular show action would typically utilize a template, but you can opt for a ViewComponent instead if it suits your needs.
00:10:08.360
Let's shift our focus to Hotwire now. I assume everyone is familiar with the basic components of Hotwire, which include Turbo Frames, Turbo Streams, Stimulus, and standard Turbo functionality.
00:10:45.760
It’s worth mentioning that Hotwire is not exclusive to Rails applications; it can be applied in other frameworks as well. For instance, Turbo Laravel is an adaptation of Hotwire designed for use with the Laravel framework.
00:11:06.000
It’s crucial to recognize that Hotwire materials are branded and structured differently, emphasizing that they can exist outside of Rails.
00:11:30.880
A common source of confusion arises with Turbo Streams, as there are two types: HTTP Turbo Streams and WebSocket broadcasts. The WebSocket broadcasts are specific to Rails and do not function out-of-the-box with other technologies.
00:12:45.760
If we imagine a few years ago, many of you may have worked with AJAX and .js.erb templates. In a way, the HTTP Turbo Streams represent a rebranding of those templates where you could replace direct HTML elements in response to user actions.
00:13:10.960
Now, I would like to show you a live demo. Over the past year, we've developed numerous features using Hotwire, and I’ll demonstrate what you can accomplish with it.
00:13:55.520
Here’s an index page presenting a list of records. When I refresh the page, you'll see new records loading asynchronously.
00:14:00.880
As I scroll, new requests are being made to the server, ensuring that rather than loading a single heavy page, only necessary records appear as they become visible. If one record encounters an issue while loading, it won't block the entire page from rendering.
00:14:20.960
Instead of one large request, you can make multiple smaller ones, which is far more efficient. Now, let me show you how the search functionality works.
00:14:55.760
As I type, you'll see the reset filters button appear once filters are applied, and the URL updates without refreshing the page.
00:15:07.760
When I continue typing, the results update in real-time. You can also add filters interactively without any need for page reloads.
00:15:26.880
In the upcoming slides, I will delve into the background of how all of this operates.
00:15:39.680
This new design represents a significant improvement over the previous index page, where functionality lacked the finesse of the current design built with Turbo Streams and Turbo Frames.
00:15:57.840
Here’s a model that appears when you open the page. It’s like a survey form where you can select various options and proceed through stages seamlessly.
00:16:12.560
This approach provides a smooth user experience, allowing for sequential selections without traditional page refreshes.
00:16:25.920
In addition, when you submit the form or change input values, modifications are efficiently tracked, and only relevant changes are reflected, enhancing the overall fluidity.
00:16:48.960
Let me walk you through multi-step forms as well. For instance, I can navigate through selection conditions, and if any errors occur, they can be rendered on the fly.
00:17:11.560
Here’s an API tokens page. In this scenario, you assign a token a name, generate it once, and you can see the token displayed without the possibility of retrieving it again.
00:17:27.040
Another feature I’m fond of is the folder-like structure, which allows for intuitive navigation as you progress through files.
00:17:43.760
In summary, using Turbo Frames makes it exceptionally easy to create models that can work independently of each other, avoiding full-page refreshes while ensuring that only the pertinent content is updated live.
00:18:02.960
Whether viewing a list of items or interacting with the application, loading records separately is seamless, preserving performance.
00:18:12.320
Now, when a user interacts with the page, it will lead to updates for only relevant components without disrupting the entire user experience.
00:18:25.920
Mixing Turbo Streams and Turbo Frames effectively allows extensive customization in how content is rendered and displayed.
00:18:47.040
The asynchronous loading feature is a standout advantage, allowing for separate and customizable user interactions within the same application.
00:19:02.160
In practice, you can create nested Turbo Frames wherein elements can be updated independently based on user actions without any interruptions.
00:19:22.960
This modular structure lets you develop an intuitive framework for handling user content dynamically.
00:19:30.160
When working with Turbo Streams, you'll often have a combination of notifications for specific users and global notifications.
00:19:52.480
Incorporating empty tags for Turbo Frame models and potential placeholders for flash messages is also a common practice among the developers utilizing Hotwire.
00:20:12.320
Each Hotwire application usually includes Stimulus controllers for various components, including dropdowns, tabs, checkboxes, and more.
00:20:30.000
It's important to remember that Turbo Frames, Streams, and Stimulus can function independently. They don’t necessarily require one other to operate, though their integration offers opportunities to create powerful applications.
00:20:52.080
Let me show you an example from one of my pages. As I type something, the main content gets refreshed. Turbo Frame actions allow URL updates while independent Turbo Streams manage the reset filters function.
00:21:14.560
For seamless infinite pagination, you can render Turbo Frames inside Turbo Streams effectively, allowing content to load dynamically based on user interaction.
00:21:39.680
It's remarkable how scalable your application can be with just a few lines of JavaScript in conjunction with the Hotwire stack.
00:21:57.040
The Stimulus framework is relatively easy to pick up and plays a supportive role alongside Turbo Frames and Streams.
00:22:14.320
Let me share another example with dynamic forms. The classical challenge of having coordinated state like country and city selections can be addressed seamlessly through Hotwire.
00:22:28.320
In this example, a hidden button works with a Turbo Frame. When you select a country, it triggers an event that re-renders the state selections based on the parameters submitted dynamically.
00:22:51.040
Challenges arise, for instance, when conditionally adding new fields to a form. It’s crucial to define the HTML structure appropriately so components can interact as desired.
00:23:12.080
Managing the visibility and relevance of form fields effectively balances user experience and application functionality.
00:23:29.920
In summary, ViewComponent plays a vital role in structuring Ruby on Rails monolithic stacks and facilitates effective communication with design teams.
00:23:45.440
Hotwire exists independently of Rails, and utilizing Turbo Frames and Turbo Streams can greatly enhance application capabilities.
00:24:02.720
I encourage you to experiment with both technologies in isolation, as you'll soon discover which functionality suits your specific needs better.
00:24:22.080
Understanding the different types of Turbo Streams is also essential; the HTTP version responds to requests made by the client, while WebSocket updates are broadcast to any listeners of the same channel.
00:24:36.800
With the addition of simple Stimulus controllers, you can extend the functionality of Turbo Frames and Streams, resulting in a more powerful user experience.
00:25:00.320
If you feel you've exhausted Hotwire's potential, remember there are additional frameworks like Stimulus Reflex and Action Cable, which can further enhance your applications.
00:25:15.520
Even in an environment where Hotwire does not exist, other server-side rendering technologies like Htmx or Phoenix LiveView can achieve comparable functionality.
00:25:42.720
As I conclude, I invite you to connect with me on Twitter, and thank you for your attention throughout my talk.
00:25:58.560
Now, I’m ready to take any questions you might have.
00:26:01.360
Thank you for the opportunity to share my thoughts on using Hotwire and ViewComponent effectively.
00:26:07.200
I hope this inspires you to explore these technologies further.