Nitro

Going further

Rendering

Nitro's rendering is fine-grained. Each dynamic part of a view knows which properties it reads, so when a property changes, only those parts run and only their nodes change. Nothing is compared.

On this page

When Nitro compiles a view, every dynamic part of it records which properties it reads. A dynamic part is an echo, an attribute, an @if, a @foreach or a child's props. When a property changes, only the parts that read it run again, and each one updates its own node.

Only what changed live, in this page View source ↓
Clicked 0 times Hello, Ada
  • Ada
  • Alan
  • Barbara
  • Donald
  • Edsger
  • Frances
  • Grace
  • Hedy
  • Ivan
  • Joan
  • Ken
  • Linus
  • Margaret
  • Niklaus
  • Radia
  • Shafi
  • Sophie
  • Tim
  • Vint
  • Whitfield

Click, type or add an author: what changes flashes.

Click +, and only one number flashes. Type a name, and only the greeting changes. Add an author, and one new row is added while the twenty rows already there are left alone.

The component

Browser + server
<?php

namespace App\Nitro\Components;

use Nitro\Component;

class RenderDemo extends Component
{
    public int $count = 0;

    public string $name = 'Ada';

    public array $authors = [
        'Ada', 'Alan', 'Barbara', 'Donald', 'Edsger', 'Frances', 'Grace', 'Hedy', 'Ivan', 'Joan',
        'Ken', 'Linus', 'Margaret', 'Niklaus', 'Radia', 'Shafi', 'Sophie', 'Tim', 'Vint', 'Whitfield',
    ];

    public function increment(): void
    {
        $this->count++;
    }

    public function addAuthor(): void
    {
        $this->authors[] = 'Author '.(count($this->authors) + 1);
    }
}

How Nitro tracks what each part reads

Each highlighted line below reads one property, so it runs again only when that property changes:

Blade
<div>
    <button nitro:click="increment">+</button>
    <p>Clicked {{ $count }} times</p>      {{-- reads $count --}}
    <p>Hello, {{ $name }}</p>               {{-- reads $name, so a click leaves it alone --}}

    @foreach ($authors as $author)          {{-- reads $authors, so neither one changes it --}}
        <li>{{ $author }}</li>
    @endforeach
</div>

Here is how this compares with other frameworks, when one property changes:

What runs again What is compared
Livewire The whole view, on the server The new HTML against the page
React, Vue The component's render function The new virtual DOM against the last one
Nitro The expressions that read the property Nothing. Each expression updates its own node
  • Methods are followed. Nitro works out what a part reads at compile time, through the methods it calls. An echo of $this->total() reads whatever total() reads.
  • #[Computed] values are cached until the state they read changes.
  • $errors, $this->shared() and $this->flashed() are tracked just like properties.
  • Updates from the server work the same way. A #[Server] answer, a reload or a parent's new props only render the parts that read what changed.
  • Keyed lists (nitro:key, :key) move, add and remove rows, and leave the other rows alone.

Choosing how elements are created

The browser creates new elements when you visit a page, when an @if turns true, or when a list gains rows. The nitro.rendering setting decides how it creates them. The result is the same either way, and the first page load always uses the server's HTML as it is.

PHP
// config/nitro.php
'rendering' => 'clone',   // Or 'create'.
Setting How elements are created
'clone' (default) Each static part of a view is built once, then copied
'create' Every element is created one by one

Next steps