Compile-time functions for Solid 2.0
Plain code in.
Solid out.
solid-labels adds compile-time functions to Solid. Write $signal, $memo and $effect as ordinary variables and calls. The compiler replaces them with Solid primitives before your bundler runs.
let count = $signal(0);
const double = $memo(count * 2);
count += 1;
console.log(double);Compiled output: let [count, setcount_1] = _createSignal(0); const double = _createMemo(() => count() * 2); setcount_1(current_1 => current_1 += 1); console.log(double());
Plain syntax
Reactive variables read and write like any other variable. There are no accessor calls to remember.
Gone at build time
Nothing from solid-labels ships to the browser. The output is the Solid code you would have written by hand.
No imports
The Solid APIs that the output needs are imported for you, and the compile-time functions are typed globally.
Oxc parser
Parsing runs at native speed. Your formatting survives, and source maps map every character.
#Signals read like variables
A $signal is a variable. Read it, assign to it, increment it. The compiler turns each use into the accessor and setter calls that Solid needs.
let count = $signal(0);
const label = $memo(`Clicked ${count} times`);
function onClick() {
count += 1;
}import { createSignal as _createSignal } from "solid-js";
import { createMemo as _createMemo } from "solid-js";
let [count, setcount_1] = _createSignal(0);
const label = _createMemo(() => `Clicked ${count()} times`);
function onClick() {
setcount_1(current_1 => current_1 += 1);
}import { createSignal as _createSignal } from "solid-js";
import { createMemo as _createMemo } from "solid-js";
let [count, setcount_1] = _createSignal(0, { name: "count" });
const label = _createMemo(() => `Clicked ${count()} times`, { name: "label" });
function onClick() {
setcount_1(current_1 => current_1 += 1);
}#Effects find their own dependencies
Solid 2.0 splits an effect into a tracked step and an untracked step. $effect writes both. It reads every signal the callback uses in the tracked step, and hands the values to the callback.
let count = $signal(0);
$effect(() => {
document.title = `Count: ${count}`;
});import { createSignal as _createSignal } from "solid-js";
import { createEffect as _createEffect } from "solid-js";
let [count, setcount_1] = _createSignal(0);
_createEffect(() => [count()], effectCallback_1);
function effectCallback_1([count]) {
document.title = `Count: ${count}`;
}import { createSignal as _createSignal } from "solid-js";
import { createEffect as _createEffect } from "solid-js";
let [count, setcount_1] = _createSignal(0, { name: "count" });
_createEffect(() => [count()], effectCallback_1);
function effectCallback_1([count]) {
document.title = `Count: ${count}`;
}#Props stay live when you destructure them
$component accepts a destructured parameter and keeps every prop reactive.
const Greeting = $component(({ name, excited = false }) => (
<p>
Hello, {name}
{excited ? '!' : '.'}
</p>
));const Greeting = (props_1) => {
const name = () => props_1.name,
def_1 = false,
excited = () => { const value_1 = props_1.excited; return value_1 === void 0 ? def_1 : value_1; };
return (
<p>
Hello, {name()}
{excited() ? '!' : '.'}
</p>
);
};