DEV Community

Rei
Rei

Posted on

Rails developers should embrace Web Component

Rails 8 will continue to use Hotwire as the default, which I think is great. Hotwire is a server-side renderingfront-end solution. Since the server is the source of data, most applications can solve problems through server-side rendering without considering data synchronization.

However, just because it can be done doesn't mean it's optimal. There are still some issues that need to be handled on the client side, usually involving client-side state and front-end rendering. For example, a multi-select input box. Currently, Geeknote's tag input uses the hotwire_combobox library, which fully utilizes Hotwire's server-side rendering features to implement a multi-select input box in a clever way. But if the network is slow, you will find that the input has a delay:

Image description

The problem here is that when converting the input to a chip, hotwire_combobox uses server-side rendering, which can actually be done on the client side because the data needed for rendering has already been obtained when displaying the autocomplete list. Of course, hotwire_combobox may switch to client-side rendering in the future, and then you will find that you need to handle two issues: client-side state and rendering. Since Hotwire does not include client-side rendering capabilities, it would be very painful to handle it purely with JavaScript. Consider how to manage options, entered values, and current selections, and reflect them in the UI?

At this point, you need to consider a front-end solution.

Front-end Components

In the past decade of front-end framework battles, the concept of "components" has gained consensus. A component is a front-end module that includes styles, state, and functionality. Components can contain more components, and components can communicate with each other. Managing front-end code in a component-based way is the mainstream in today's front-end frameworks.

So when choosing a front-end solution, I will consider component-based front-end solutions.

Available Solutions

View Component

If you search for Rails Component, you will find the ViewComponent gem. It is essentially an object-oriented server-side partial template that provides better testing interfaces but does not solve client-side state and rendering.

React/Vue, etc.

React/Vue and other popular front-end frameworks can easily build front-end components. They usually provide reactive properties and declarative templates, which can handle client-side state and rendering well. And these frameworks have large communities with a lot of ready-made UI libraries and component libraries.

But this front-end frameworks have a problem: poor interoperability. React components need to be used in React projects, and Vue components need to be used in Vue projects. Of course, you can add adapters to make components from different frameworks interoperate, but few people do this. Usually, once a framework is chosen, the entire application will choose components based on that framework.

Due to this problem, using React/Vue in Rails View also seems weird. Based on my experience, introducing React/Vue into Rails View will eventually lead to front-end and back-end separation because these components cannot interact with Rails View. Instead of coupling them together, it is better to separate them completely.

Some people may think this is good, but I hope front-end components are used to enhance rather than replace Rails View, because Rails View work well at server-side rendering.

Web Component

Finally, I turned my attention to Web Component, a standard browser API. Web Component allows developers to create custom elements and use them like built-in browser elements.

For example, you can use custom elements like this:

<form action="/posts" method="post">
  <my-combobox name="tabs" value="Ruby,JavaScript" suggest-url="/tags/suggests"></my-combobox>
</form>
Enter fullscreen mode Exit fullscreen mode

<my-combobox> is a custom element that works like a built-in browser element and will be submitted with the form.

I haven't implemented <my-combobox> yet, maybe in the future.

For Rails projects, it is better because you can use custom elements in the Turbo Stream/Broadcast without additional initialization code.

You can create custom elements directly with the browser API, but I recommend starting with the Lit library.

Introduction to Lit

Lit is a library for developing Web Components, mainly developed by Google. According to the official introduction, the Lit development team participated in the formulation of the Web Component standard.

Compared to the native browser interface, Lit provides more features , such as:

  • Scoped styles.
  • Reactive properties.
  • Declarative templates.

Here is an example of a counter component implemented with Lit:

import { LitElement, html, css } from 'lit';

class MyCounter extends LitElement {
  static styles = css`
    label {
      color: green;
    }
  `

  static properties = {
    count: { type: Number }
  }

  constructor() {
    super()
    this.count = 0
  }

  increment() {
    this.count += 1
  }

  render() {
    return html`
        <label>${this.count}</label>
        <button @click="${this.increment}">Increment</button>
    `;
  }
}

customElements.define('my-counter', MyCounter);
Enter fullscreen mode Exit fullscreen mode

Note that:

  • Styles within the component are only effective for internal elements, so class names can be written very concisely.
  • Use ${} for interpolation and @event for event binding.
  • When the count property changes, only the parts that need to be updated will be updated.

These features can greatly simplify front-end component development.

Practice

Recently, I developed a project called Geekslide using Lit, which is used for UI component and slide editing/playback.

Image description

Without Lit, such interactions would be very hard to write manually. Due to the excellent interoperability of Web Components, I can use Lit when needed without completely replacing Rails View.

I plan to update more content on Lit practices in the future.

Resources

Finally, I recommend some resources.

The best place to learn Lit is the official documentation: https://lit.dev/docs/

Adobe's UI library has a Web Component version: https://opensource.adobe.com/spectrum-web-components/

The FontAwesome team is developing a UI library based on Web Components: https://backers.webawesome.com/

Summary

If you need to develop interactive applications and don't want to replace the default Rails View stack, try Web Components / Lit.

Top comments (0)