React

Isole interattive in Astro: quando parte il JavaScript

In Astro una pagina nasce senza JavaScript: ogni componente con una direttiva client è un’isola che idrata da sola, con il suo bundle e il suo costo.

In sintesi

  • Un file .astro produce HTML e CSS; il JavaScript arriva solo da un’isola con direttiva client.
  • Le direttive client valgono sui componenti di framework, non sui componenti .astro.
  • Due isole non condividono stato: per un valore comune serve uno store esterno.

In Astro il JavaScript di un componente parte solo se lo dichiari: un file .astro produce HTML e CSS, e l’interattività arriva da un’isola con una direttiva client:. La pagina statica resta statica anche quando contiene un widget interattivo.

La direttiva decide il momento

DirettivaIdrata quandoCaso d’uso
client:loadSubito, all’idratazioneControllo visibile sopra la piega
client:idleAl primo momento liberoWidget che non blocca la lettura
client:visibleQuando entra nel viewportContenuto sotto la piega
client:mediaQuando la media query è veraMenu mobile
client:onlySolo nel browserComponente che non regge il rendering sul server
npx astro add react

L’integrazione aggiunge il renderer: senza, Astro non sa compilare un componente React, Vue o Svelte. Ogni framework ha il suo comando e puoi averne più di uno nella stessa pagina, al costo di un runtime per framework.

---
import Counter from "../components/Counter.jsx";
import Reviews from "../components/Reviews.jsx";
---


Le props attraversano il confine verso il browser e devono essere serializzabili: una funzione o una classe non arriva all’isola. Le direttive client: valgono solo sui componenti di framework, non sui file .astro.

Un’isola, un bundle

Ogni isola idrata da sola: due isole non condividono stato per il solo fatto di stare nella stessa pagina. Per un contatore condiviso serve uno store esterno, come nanostores, sottoscritto da entrambe le isole.

// src/stores/cart.js
import { atom } from "nanostores";

export const cartCount = atom(0);

// in ogni isola
// import { useStore } from "@nanostores/react";

Contenuto statico e isole server

Il testo resta HTML: non trasformare una pagina intera in una sola isola per comodità. Astro 5 aggiunge le isole server con server:defer, che rendono il contenuto sul server e idratano solo il guscio interattivo.

Il limite da mettere in conto

Un’isola paga il runtime del suo framework: due isole dello stesso framework condividono il codice, ma ognuna ha il proprio componente e il proprio stato. Con client:only il componente non viene reso sul server, quindi non è nell’HTML iniziale e non porta contenuto ai crawler.

Errori che si vedono

  • Mettere client:load su tutto: la pagina torna a costare come una SPA.
  • Usare client:visible su un elemento sempre in cima: il risparmio è zero e il contenuto salta.
  • Aspettarsi che due isole condividano lo stato: ognuna ha la propria istanza.
  • Passare un callback come prop a un’isola: la funzione non attraversa il confine.

Le isole si riempiono con componenti già pronti: saastro e Astro Association si installano come sorgente, e il blocco hero resta statico finché non gli aggiungi una direttiva. La direttiva che manca è descritta in client directive mancante, il confronto con Next.js in Astro vs Next.js, il routing di un altro framework in routing e layout in SvelteKit.

Domande frequenti

Quando serve client:load?

Quando il componente è visibile subito e deve rispondere al primo clic. Per tutto il resto parti da idle o visible: il caricamento immediato annulla il vantaggio di Astro.

Le isole possono condividere stato?

Non da sole. Ogni isola è un’istanza separata: per condividere un valore serve uno store esterno come nanostores, sottoscritto da entrambe.

Astro supporta Vue e Svelte insieme?

Sì. Ogni integrazione aggiunge un renderer e le isole possono usare framework diversi nella stessa pagina. Il costo è un runtime per framework.

client:only a cosa serve?

Serve quando il componente non può essere reso sul server, per esempio perché legge window subito. In cambio perdi l’HTML iniziale di quel blocco.

Il contenuto dentro un’isola è indicizzabile?

Sì, se l’isola viene resa sul server: client:idle e client:visible lasciano l’HTML nel documento. Con client:only il markup arriva solo dal browser.