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.

Get startedOpen the REPL

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>
);
};

Try your own code

Open the REPLRead the reference