Lit and Rimmel are some relatively similar libraries as they both make use of tagged templates.
There are some key differences which we're going to explore here
Architecture and Programming Paradigm
Lit is a simple, lightweight library for building web components using JavaScript or TypeScript. It uses a reactive update system where changes in data trigger updates to the DOM. It leverages JavaScript template literals for HTML templating, encapsulated in its html tagged templates.
Rimmel emphasizes functional/reactive programming approach, by leveraging observable streams. This library focuses on using RxJS's Observables, Subjects, and BehaviorSubjects to create and manage UI state and behaviors, which can lead to more declarative and predictable UI code.
Templating and Data Binding
Lit offers a simple templating syntax with html
and css
tagged templates with its own set of custom directives for advanced functionality like repeating templates, guarding updates, and managing attributes. It has built-in reactive data binding.
Rimmel utilises a single rml
tagged template that remains faithful to the HTML syntax, with a twist that template expressions can also be Promises and Observables and will be bound directly wihout the use of a custom DSL.
Component Model
Each Lit component is a class that extends HTMLElement, allowing the use of lifecycle callbacks and state management features provided by the web component standards.
Rimmel Components are designed as plain functions, including web components, which may appeal to developers looking for a more functional style of programming. This approach can make components easier to test and maintain.
State Management
Lit manages state internally within components or through external libraries. The state handling is less declarative compared to Rimmel but fits well within the object-oriented paradigm.
Rimmel doesn't deal with application state management at all. That aspect is entirely delegated to your application streams, so if you use RxJS, which is the most powerful general-purpose streams library that you can also use for state management despite not even being labelled as a state manager, you can manage even the most advanced state with unmatched ease.
Community and Ecosystem
Lit is backed by Google and has a larger community and ecosystem. This popularity brings more third-party tools, libraries, and plugins that integrate well with it.
Rimmel, as a novel library, and a smaller user base has the ability to grow faster. Its natural integration with RxJS could attract developers looking for advanced functional/reactive solutions.
Performance
Lit adopts various engineering tricks to make updates fast through its virtual DOM. Rimmel, on the other hand, uses no virtual dom and instead it just binds event handlers to streams and the real DOM, which means fine-grained reactivity and updates are among the fastest available.
Use Case Suitability
Both Lit and Rimmel are suitable for a wide range of projects. The former fits more where traditionally-structured OOP approaches are preferred, whilst the latter shows it true power in the functional, point-free paradigm.
Action
Let's compare both with a code example: a little component with two buttons that prints "Hello" when both are clicked.
import { LitElement, html, css } from 'lit';
class HelloButtons extends LitElement {
static properties = {
firstClicked: { type: Boolean },
secondClicked: { type: Boolean },
showMessage: { type: Boolean }
};
constructor() {
super();
this.firstClicked = false;
this.secondClicked = false;
this.showMessage = false;
}
firstButtonClicked() {
this.firstClicked = true;
this.checkBothClicked();
}
secondButtonClicked() {
this.secondClicked = true;
this.checkBothClicked();
}
checkBothClicked() {
if (this.firstClicked && this.secondClicked) {
this.showMessage = true;
}
}
render() {
return html`
<button @click="${this.firstButtonClicked}">Button 1</button>
<button @click="${this.secondButtonClicked}">Button 2</button>
<div>${this.showMessage ? 'Hello' : ''}</div>
`;
}
}
customElements.define('hello-buttons', HelloButtons);
const element = document.createElement('hello-buttons');
document.body.appendChild(element)
Follwing is the Rimmel example, managing state exclusively as RxJS streams. You may notice how shorter did the code become as a result:
import { BehaviorSubject, zip, take } from 'rxjs';
import { rml } from 'rimmel';
function HelloButtons() {
const first = new Subject();
const second = new Subject();
const msg = zip([first, second]).pipe(
map(() => 'Hello'),
take(1)
);
return rml`
<button onclick="${first}">Button 1</button>
<button onclick="${second}">Button 2</button>
<div>${msg}</div>
`;
}
document.body.innerHTML = HelloButtons();
Which programming paradigm do you prefer, or find more promising?
Imperative or Functional? Object-Oriented or Streams-Oriented?
Leave a comment below.
Problem is many developers discount vanilla JS too soon,
grabbing for "tools" that make work "easier"
But a fool with a tool, is still a fool. Offloading intelligence to a Library or a Compiler
Ask such an "expert" to not use a tool, and they probably fail.
(JSFidlle Result tab loads slow)