SolidJS: A Truly Reactive JavaScript Framework

3 min

1. The “Holy Grail” of Frontend Frameworks: Performance and Experience

Since React popularized the Virtual DOM, the VDOM has seemed to become standard equipment for modern frontend frameworks. By maintaining a virtual representation of the UI in memory and using a diff algorithm to calculate the minimum DOM updates, it improves both the developer experience and performance in most scenarios.

But the VDOM is not free. It consumes memory, and the diffing process also has a computational cost. This raises a question: can we bypass the VDOM and apply state changes precisely to the DOM while retaining a declarative, React-like development experience?

SolidJS provides its answer.

2. The Core of SolidJS: Fine-Grained Reactivity

SolidJS is a declarative, reactive JavaScript framework. Although it uses JSX and looks very similar to React, its underlying principles are completely different.

The SolidJS compiler transforms JSX code into optimal native DOM operations. Instead of using a VDOM, it builds a dependency graph composed of reactive “Signals.” When the value of a signal changes, only the “Effects” or computations (Memos) subscribed to that signal run again.

A disruptive mental model: components run only once!

In React, the entire component function runs again when state or props change. In SolidJS, however, your component function runs from beginning to end only once.

import { createSignal } from 'solid-js';

function Counter() {
  console.log('Component function runs!'); // 这句话只会在组件挂载时打印一次

  const [count, setCount] = createSignal(0);

  const increment = () => setCount(count() + 1);

  return (
    <button type="button" onClick={increment}>
      Count: {count()}
    </button>
  );
}

When you click the button, only the reader of the count() signal and the DOM text node that depends on it are updated. The Counter function itself does not run again. This “surgical” update is the source of SolidJS’s exceptional performance.

3. Core APIs

The SolidJS reactivity system is mainly composed of three core primitives:

  • createSignal(initialValue): Creates a reactive signal and returns a getter and a setter: [count, setCount].
  • createEffect(() => {}): Creates an “effect” that automatically tracks every signal read inside it and runs again when any of those signals changes. It is ideal for side effects such as manually manipulating the DOM.
  • createMemo(() => {}): Creates a cached, derived computed value. It recalculates only when one of its internal signal dependencies changes.
import { createSignal, createEffect } from 'solid-js';

function App() {
  const [firstName, setFirstName] = createSignal('John');
  const [lastName, setLastName] = createSignal('Smith');

  // createEffect 会在 firstName 或 lastName 变化时自动运行
  createEffect(() => {
    console.log(`Full name: ${firstName()} ${lastName()}`);
  });

  // ...
}

4. Why Choose SolidJS?

  • Exceptional performance: SolidJS often ranks near the top in independent benchmarks, with performance very close to native JavaScript code.
  • Extremely small bundle size: Because there is no VDOM runtime, its core package is very small.
  • Familiar developer experience: If you are familiar with React Hooks, you can get started with SolidJS quickly. The combination of JSX and reactive primitives is both powerful and intuitive.
  • True reactivity: Its model is closer to MobX or Vue’s Composition API, but the compiler makes it possible without runtime overhead.

Conclusion

SolidJS represents an important direction in the evolution of frontend frameworks: using the compiler to do more work at build time in exchange for less runtime code and higher performance. It proves that we can escape the constraints of the Virtual DOM without sacrificing a declarative development experience. For applications that pursue exceptional performance, SolidJS offers a highly attractive choice.