Da Gatsby ad Astro - I componenti Astro

Nell’articolo precedente abbiamo esaminato la struttura di un progetto creato con Astro. Abbiamo accennato all’esistenza di pagine e di componenti, ma non abbiamo parlato di come crearli. Questo articolo spiegherà cos’è un componente di Astro e come questi componenti vengono utilizzati nel nostro progetto.

Cosa sono i componenti Astro

Molti framework si basano sull’idea di avere dei blocchi di codice riutilizzabili che gestiscono la logica e la grafica di vari pezzi del nostro sito. Per esempio, l’articolo che state guardando è composto da vari componenti: l’header del sito è un componente, così come la tabella dei contenuti, il blocco che mostra gli articoli correlati, ecc…

In Gatsby, il generatore che utilizzavo prima per il mio sito, l’html per questi componenti viene generato utilizzando il framework React, con cui molti sviluppatori sono oramai familiari. Un componente in React ha un aspetto simile a questo:

export function PostHeading({title, date}) {
    const formattedDate = date.toLocaleDateString();
    return (
        <div>
            <h1>{title}</h1>
            <p>{formattedDate}</p>
        </div>
   );
}

Come possiamo notare, qui viene eseguita della logica (la formattazione della data) e viene anche indicato come valore di ritorno della funzione il codice html che deve essere generato, con le nostre variabili già inserite nel codice.

In seguito, questo componente potrà essere sfruttato in altri componenti come se fosse un elemento HTML:

// Si importa il componente dal file
import PostHeading from './PostHeading.js';

export function Post({post}) {
    // ...

    // Lo si usa come tag all'interno del codice HTML
    return (
        <div>
            <PostHeading title={post.title} date={post.date} />
            {/* ... */}
        </div>
    );
}

Ok, ma forse vi chiederete: “Perché concentrarsi così tanto sulla struttura di un componente in React? Non stavamo parlando di Astro?”

Ci sono due motivi per cui è utile conoscere questa struttura:

  1. Astro supporta anche React, quindi volendo possiamo usare i componenti di quel framework all’interno del nostro sito e tutto funzionerebbe correttamente
  2. I componenti di Astro sono abbastanza simili nel loro funzionamento

Il componente PostHeading indicato sopra, se trasformato in un componente Astro, avrebbe questo aspetto:

---
const { title, data } = Astro.props;
const formattedDate = data.toLocaleDateString();
---
<div>
    <h1>{title}</h1>
    <p>{formattedDate}</p>
</div>

Come potete notare, i componenti Astro sono (a mio parere) perfino più intuitivi di quelli in React!

Il codice Javascript che gestisce la logica del componente (estrarre dati, formattarli, richiederli, ecc…) lo mettiamo tutto all’inizio, racchiuso fra le due “recinzioni” (questo è il termine inglese usato nella documentazione) formate da 3 lineette.

Il codice html viene invece inserito appena dopo, senza la necessità che il tutto sia racchiuso in una funzione.

Come in React, possiamo utilizzare questo nostro componente come se fosse un elemento HTML:

---
import PageHeading from './PageHeading.astro';
const { post } = Astro.props;
---
<div>
    <PostHeading title={post.title} date={post.date} />
</div>

Dove utilizzare i componenti Astro

In pratica, questi componenti vengono utilizzati per generare il sito nella sua interezza. Questo significa che ogni pezzo del vostro sito sarà costruito con questo metodo, dalla homepage al layout dei post, dall’header al footer.

In genere, possiamo dividere questi componenti in 3 categorie in base al loro utilizzo:

Elementi del sito

Qui i componenti Astro vengono utilizzati nel metodo più classico: per creare pezzi di codice riutilizzabili in varie parti del sito. Nel mio sito, alcuni componenti di questo tipo sono la Tabella dei Contenuti, i blocchi che si aprono e chiudono nella pagina “Chi sono”, ogni riquadro contenente la presentazione di un progetto nella pagina “Progetti”, ecc…

Questi componenti vengono generalmente importati nelle pagine e nei layout.

Layouts

Questi componenti vengono utilizzati per racchiudere dei contenuti. Per esempio, in questo sito ogni articolo viene scritto in markdown (MDX, per essere precisi) e le pagine che vengono generate utilizzano un componente astro che ho chiamato BlogPostLayout. Questo componente prende il testo del mio articolo, lo trasforma da markdown in HTML, ne estrae le intestazioni che vengono poi passate alla Tabella dei Contenuti e racchiude il tutto con l’header e il footer che utilizzo in tutto il resto del sito.

I layout possono anche essere annidati. Per esempio, nel mio sito ho un layout per i post e uno per le pagine, ma nessuno di questi si preoccupa della generazione del tag <html> o <head>. Entrambi vengono annidati in un layout che ho chiamato Base, che aggiunge queste sezioni per tutte le pagine del sito, così che siano sempre coerenti.

Pagine

Se si vuole creare una pagina con delle sezioni particolari che non possono essere descritte in un file scritto in markdown, allora possiamo utilizzare i componenti Astro per crearla e dargli esattamente il design che desideriamo. Questo è il caso, per esempio, per la mia Homepage, e le pagine “Progetti”, “Blog” e “Chi sono”, che hanno tutte una struttura specifica e particolare.

Mettendo poi il file nella cartella giusta, Astro lo interpreterà come una pagina e lo utilizzerà di conseguenza.

Anatomia di un componente

La sintassi di un componente Astro è estremamente intuitiva. Qui di seguito vi mostro una specie di “cheat sheet” che vi aiuterà a capire dove inserire quali codici:

---
console.log(`
    Javascript che viene eseguito durante la generazione del sito,
    prima di calcolare l'html.
`);

// Possiamo indicare variabili da usare nell'HTML
const message = "Hello, world!";
---
<div>
    Al di fuori della sezione delimitata da `---`, 
    possiamo inserire il nostro html. Le variabili 
    javascript le inseriamo come faremmo in react,
    cioè racchiuse tra parentesi graffe.

    {message} ← qui ci sarà scritto: "Hello, World"
</div>

<style>
    /* 
       Codice CSS per questo componente.
       Le regole che scriveremo qui saranno abbinate solo
       agli elementi presenti in questo file, a prescindere
       da quanto le regole siano generiche. Per esempio, se
       impostiamo una regola come quella indicata sotto,
       l'effetto si noterà solo per il codice incluso in questo
       componente (le regole sono "scoped").
    */
    div {
        margin-bottom: 20px;
    }
</style>

<style is:global>
    /*
       Stili che dovranno essere applicati a qualsiasi elemento
       HTML coerente con le regole, anche se è al di fuori di
       questo componente: in pratica sono stili globali. Le regole
       indicate qui avranno però effetto solo se questo componente
       è presente nella pagina.
    */
    body {
        background-color: teal;
    }
</style>

<script lang="typescript">
    // Codice javascript/typescript che verrà eseguito
    // sul client.
</script>

Questi componenti sono molto comodi perché includono diverse funzionalità utili in automatico, senza dover fare interventi manuali.

CSS

I CSS che vengono inseriti nel tag <style> vengono automaticamente associati solo agli elementi presenti nel componente descritto nel file. Ciò significa che nei nostri CSS possiamo usare i nomi che vogliamo per le classi, senza preoccuparci se sono usati altrove oppure no, perché in ogni caso verranno modificati quando viene creato il sito, così da non avere conflitti.

Astro lascia anche la possibilità di creare stili che non sono relegati al singolo componente aggiungendo un attributo: <style is:global>. Questa opzione torna molto utile quando, nel template base del nostro sito, vogliamo creare stili globali per personalizzare la tipografia, i colori o simili.

Il javascript nella prima sezione

Il codice javascript contenuto in questa sezione (racchiuso tra ---) verrà eseguito nel momento in cui il sito viene generato da Astro. E’ il posto in cui vogliamo ottenere i dati che verranno poi visualizzati nel codice, dopo averli modificati se necessario.

Questi dati potrebbero essere i post, dei dati estratti da un file JSON o simile, oppure anche le informazioni passate come proprietà (props) al componente.

Gli script client-side

Possiamo aggiungere degli script che verranno eseguiti sul client inserendoli all’interno del tag <script>. Astro interverrà in automatico sul nostro codice per fare le seguenti cose:

  • convertire typescript in javascript, se necessario;
  • includere automaticamente le librerie importate;
  • assicurarsi che lo script venga caricato una sola volta anche se il componente è usato in vari punti.

Il prossimo articolo

Direi che abbiamo trattato abbastanza informazioni per oggi! Nel prossimo articolo, vedremo come funzionano le slot, che è il metodo utilizzato da Astro per annidare i componenti. Queste sono fondamentali per i layout e per vari componenti strutturali del sito.

A presto!