Signals: The New Wave of Frontend Reactivity
1. The Evolution of Reactive Models
The essence of frontend development is “mapping state to UI.” Over the years, we have witnessed the continuous evolution of reactive models: from manual DOM manipulation, to MVC/MVVM patterns, and then to the Virtual DOM (VDOM) popularized by React. By batching state changes and performing diffing at the component level, the VDOM greatly simplified UI development.
However, the VDOM is not a silver bullet. Its component-level rerendering and diffing overhead can become a performance bottleneck in certain highly dynamic scenarios. In recent years, an older paradigm revitalized by modern compiler optimizations—Fine-Grained Reactivity—has returned to center stage, and its core vehicle is Signals.
2. What Are Signals?
A Signal is a reactive primitive that wraps a value and automatically notifies all of its dependencies when that value changes. Unlike VDOM frameworks, which track changes at the component level, Signals automatically establish a dependency graph at the point where data is read.
When a Signal’s value is updated, only the computations (Memo) or side effects (Effect) that directly or indirectly depend on that Signal are rerun. This enables precise, “surgical” DOM updates and completely bypasses the need for VDOM diffing.
Its core usually consists of three primitives:
createSignal(value): Creates a reactive state unit.createEffect(() => {}): Creates a side effect that automatically tracks dependencies and responds to changes.createMemo(() => {}): Creates a derived, cached reactive computation.
// SolidJS 语法示例
const [count, setCount] = createSignal(0);
const doubleCount = createMemo(() => count() * 2);
createEffect(() => {
console.log(`The double count is: ${doubleCount()}`);
});
setCount(1); // 这将触发 memo 重新计算,并触发 effect 重新执行One key mental model is that, in a Signal-based framework such as SolidJS, the component function itself runs only once during initialization. Subsequent updates are driven entirely by the reactive system rather than by rerendering the component.
3. Broad Adoption Across the Ecosystem
Signals are not a completely new concept; their ideas can be traced back to early frameworks such as Knockout.js. With the help of modern JavaScript compilers, however, they have gained new vitality and been widely adopted by major frameworks:
- SolidJS & Qwik: Built entirely around Signals and considered benchmark implementations of the paradigm.
- Preact: Introduces official support through the
@preact/signalspackage, which can be integrated into existing Preact/React projects. - Vue: The
refandcomputedprimitives in its Composition API are essentially an implementation of Signals. - Svelte 5: The upcoming “Runes” update is a redesign of Svelte’s reactive model, with Signals as a central source of inspiration and implementation pattern.
- Angular: Recent versions have also introduced Signals as a new reactive primitive.
This convergence across frameworks demonstrates the value of Signals as an efficient and predictable reactive model.
4. Advantages and Trade-offs
Advantages:
- Excellent performance: By avoiding the VDOM and component-level rerendering, Signals usually perform very well in benchmarks.
- Predictability: The flow of state updates is clear and easy to understand and debug.
- Low memory usage: There is no need to maintain a virtual representation of the entire component tree.
Trade-offs:
- A different mental model: Developers accustomed to React’s rendering cycle need to adapt to the new model in which “a component runs only once.”
- Ecosystem integration: Although Signals are powerful on their own, deep integration with the vast React VDOM ecosystem—for example, certain UI libraries—may require additional adaptation work.
Conclusion
The revival of Signals marks an important evolution in frontend state-management paradigms. It shifts developers’ attention away from “how a component renders” and back toward the more fundamental question of “how state flows.” Through deep integration with compilers, Signals deliver an excellent developer experience while opening up new possibilities at the performance boundaries of Web applications.