What is SolidJS?
SolidJS is a declarative JavaScript UI framework that uses fine-grained reactivity for DOM updates without a virtual DOM.
What is SolidJS?
SolidJS is a declarative, reactive JavaScript framework for building user interfaces. Created by Ryan Carniato, it reached 1.0 in June 2021 and hit version 1.8 in late 2023, with SolidStart 1.0 (its meta-framework) shipping in early 2024. Unlike React, SolidJS doesn't use a virtual DOM. Instead, it compiles JSX templates into real DOM instructions at build time and tracks dependencies at a granular signal level. Components in Solid run once — there's no re-rendering cycle. When a signal's value changes, only the specific DOM node bound to it updates. In the JS Framework Benchmark, SolidJS consistently ranks among the top three fastest frameworks, often outperforming Svelte and React on keyed list operations. The framework ships a ~7 KB (minified + gzipped) runtime. We've used SolidJS on internal tooling dashboards where sub-10ms interaction latency and minimal bundle size were hard requirements.
How it works
Solid's core primitive is the signal — a reactive value created with createSignal. Signals return a getter function and a setter function. When you read a signal inside a tracking scope (like JSX or createEffect), Solid automatically subscribes that scope to changes.
import { createSignal, createEffect } from "solid-js";
function Counter() {
const [count, setCount] = createSignal(0);
createEffect(() => {
console.log("Count is:", count()); // auto-tracked
});
return (
<button onClick={() => setCount(count() + 1)}>
Clicked {count()} times
</button>
);
}
Key things to notice:
countis a function call, not a value. This is how Solid tracks reads.- The
Countercomponent body runs exactly once. It doesn't re-execute on state changes like a React function component would. createEffectauto-subscribes to any signals read inside it — no dependency array needed.
At compile time, Solid's Babel plugin (or Vite plugin via vite-plugin-solid) transforms JSX into efficient document.createElement and textContent assignments. There's no diffing step. The compiled output directly wires signal subscriptions to DOM mutations. This means the runtime cost is proportional to what actually changes, not the component tree size.
Solid also provides createMemo for derived computations, createResource for async data fetching with Suspense support, and createStore for nested reactive objects using proxies.
When to use it
SolidJS makes sense in specific situations — it's not a universal default.
Use SolidJS when:
- You need extreme rendering performance (real-time dashboards, data-heavy tables, animation-driven UIs)
- Bundle size is a first-class constraint (embedded widgets, third-party scripts)
- You want JSX familiarity without React's reconciliation overhead
- You're building SPAs or islands where you control the full render lifecycle
Think twice when:
- Your team is heavily invested in the React ecosystem and needs broad library compatibility (component libraries, form libraries, etc.)
- You need a massive hiring pool — React's developer community is still 10-20x larger
- Server-side rendering with deep ecosystem maturity is critical — SolidStart is good but younger than Next.js or Remix
- You're prototyping fast and need maximum third-party package availability
We reach for Solid on performance-critical internal tools and embedded widgets. For client marketing sites, we still default to Next.js or Astro.
SolidJS vs alternatives
| Feature | SolidJS | React 19 | Svelte 5 | Vue 3 |
|---|---|---|---|---|
| Reactivity model | Fine-grained signals | Re-render + diffing (compiler hints in React Compiler) | Runes (fine-grained) | Proxy-based refs/reactive |
| Virtual DOM | No | Yes | No (Svelte 5 uses blocks) | Yes |
| Runtime size (gzip) | ~7 KB | ~40 KB | ~5 KB | ~33 KB |
| Component re-execution | Once | Every state change | Once (Svelte 5) | Once (setup runs once) |
| JSX | Yes | Yes | No (custom syntax) | Optional (SFCs typical) |
| Meta-framework | SolidStart | Next.js, Remix | SvelteKit | Nuxt |
| Ecosystem maturity | Growing | Massive | Large | Large |
Solid and Svelte 5 have converged in philosophy — both use signals now — but Solid keeps JSX while Svelte uses its own template syntax. If your team already knows JSX, Solid's learning curve is shorter.
Real-world example
We built an internal analytics dashboard that renders 5,000+ rows of live-updating campaign data. The original React implementation (React 18 + react-window) averaged ~45ms interaction-to-paint on mid-tier laptops. After rewriting the table layer in SolidJS with createVirtualizer from @tanstack/solid-virtual, interaction-to-paint dropped to ~8ms. Bundle size for the table module went from 62 KB to 19 KB gzipped. The rest of the app stayed in Next.js — we loaded the Solid table as an island via a web component wrapper. Total migration time for one engineer: about four days. The tradeoff was maintaining two build pipelines, but the performance win justified it for this use case.