How Runes Are Compiled

+15 Mana ✨

Runes like $state, $derived, and $effect are not runtime functions - they're compile-time instructions that transform your code.

$state Transformation

What you write:

javascript
let count = $state(0);
count++;

What the compiler creates (conceptually):

javascript
let count = {
  value: 0,
  subscribers: new Set(),
  
  get() {
    // Track who's reading
    if (currentEffect) {
      this.subscribers.add(currentEffect);
    }
    return this.value;
  },
  
  set(newValue) {
    this.value = newValue;
    // Notify all subscribers
    this.subscribers.forEach(effect => effect.run());
  }
};

Every read/write to count is transformed to use these getters/setters.

$derived Transformation

What you write:

javascript
let doubled = $derived(count * 2);

What happens:

  1. Compiler wraps the expression in a reactive computation
  2. When count changes, the computation re-runs
  3. Only if the result differs, subscribers are notified

$effect Transformation

What you write:

javascript
$effect(() => {
  console.log(count);
});

What the compiler creates:

  1. Wraps your function as a "reactive scope"
  2. Tracks which reactive values are read during execution
  3. Re-runs the function when any dependency changes
  4. Handles cleanup when dependencies change or component unmounts

Why "Runes" and Not Functions?

Runes look like function calls, but they're actually compiler macros:

javascript
// This doesn't work - $state isn't a real function!
const createState = $state; // āŒ Error

// Runes must be used directly
let count = $state(0); // āœ… Compiler transforms this

The compiler sees $state(0) and transforms the entire variable declaration.

šŸ“– Runes documentation

āœ“ Completed