BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Performance-Focused Reactive UI Framework Solid.JS Releases First Major Version

Performance-Focused Reactive UI Framework Solid.JS Releases First Major Version

Solid.js, which self-describes as a reactive JavaScript UI library, recently released its first major iteration. Solid replicates many capabilities (e.g., server-side rendering, concurrent rendering) and APIs (e.g., stores, context, directives) available in other UI frameworks. Developers describe how the appearance and behavior of user interfaces relate to a set of reactive dependencies. Solid compiles the statements to imperative DOM operations.

Web applications are reactive applications whose behavior is the specification of how the application reacts to incoming events. That reaction typically consists of updating the state of the application and executing commands that affect the systems the application interfaces with. Solid lets developers reify the state of the application as reactive values and bind events to state updates and command execution.

A simple application that iterates through a list of colors every second

demo application with Solid

may be defined in pseudo-code by the following declarative statements:

colors ≡ ["blue", "red", "green"]
index  ≡ count mod 3
color  ≡ colors[index]
init => count <- 0, set recurring timer
exit => cancel timer
second elapsed => count <- count + 1
color update => render <div style={{color: color()}}>Color: {color()}</div>;

The previous pseudo-code showcases reactions (event => reactions), which may update variables (signals) and execute commands (effects), and equations (x ≡ y). Equations are implemented with Solid’s derived signals, which ensure that anytime the right hand changes, the left hand is updated to maintain the equality.

The previous pseudo-code translates to Solid’s APIs as follows:

import { render } from  "solid-js/web";
import { createSignal, onCleanup, onMount } from  "solid-js";

function  Counter() {
  // `colors` is a constant so no need to use a signal
  const  colors  = ["blue", "red", "green"];
  // `count` signal
  const [count, setCount] =  createSignal();
  let  timer;
  // Derived signals
  const  index  = () =>  count() %  3;
  const  color  = () =>  colors[index()];

  // init event handler
  onMount(() => {
    setCount(0);  
    timer  =  setInterval(() =>  setCount(count() +  1), 1000);
  });

  // exit event handler
  onCleanup(() =>  clearInterval(timer));

  // Baked-in render command handler
  // will automatically detect the reactive dependencies (`color`)
  // that trigger the render command
  return <div  style={{color: color()}}>Color: {color()}</div>;
}

// Starting the application
render(() => <Counter />, document.getElementById('app'));

Solid’s compiler then compiles the previous code to optimize the rendering process:

import { template, render, createComponent, insert, effect } from 'solid-js/web';
import { createSignal, onMount, onCleanup } from 'solid-js';

const _tmpl$ = template(`<div>Color: </div>`, 2);

function Counter() {
  const colors = ["blue", "red", "green"];
  const [count, setCount] = createSignal();
  let timer;

  const index = () => count() % 3;

  const color = () => colors[index()];

  onMount(() => {
    setCount(0);
    timer = setInterval(() => setCount(count() + 1), 1000);
  });
  onCleanup(() => clearInterval(timer));
  return (() => {
    const _el$ = _tmpl$.cloneNode(true);
          _el$.firstChild;

    insert(_el$, color, null);

    effect(() => _el$.style.setProperty("color", color()));

    return _el$;
  })();
}

render(() => createComponent(Counter, {}), document.getElementById('app'));

The previous code showcases the creation of a DOM template (template('<div>Color: </div>', 2)) that will be cloned (cloneNode) and updated in place only where necessary (e.g., _el$.style.setProperty("color", color())). Solid.js thus avoids using a virtual DOM and the associated overhead (virtual DOM computation, virtual DOM diffing). Instead, the compiled code provides both optimized creation and updates of actual DOM nodes.

The direct DOM updates may have the additional advantage of removing an abstraction layer that only imperfectly replicates the DOM (e.g., React’s SyntheticEvent vs. native DOM events, React’s partial support of web components) and has been the source of accidental complexity and bugs.

Solid boasts advanced features that made their way to recent releases of popular UI frameworks (<Suspense>, <SuspenseList>, useTransition). Solid 1.0 ships with a dedicated site that includes plenty of documentation, tutorials, and a code playground. Solid.js is open-source software distributed under the MIT license.

Rate this Article

Adoption
Style

BT