Salta ai contenuti

Opzionale: Crea una raccolta di contenuti

Ora che hai un blog che utilizza il routing basato su file integrato di Astro, lo aggiornerai per usare una raccolta di contenuti (EN). Le raccolte di contenuti sono un modo potente per gestire gruppi di contenuti simili, come articoli di blog.

Preparati a…

  • Sposta la tua cartella di articoli del blog in src/blog/
  • Crea uno schema per definire il frontmatter del tuo articolo del blog
  • Usa getCollection() per ottenere contenuto e metadata degli articoli del blog

Anche quando usi raccolte di contenuti, userai comunque la cartella src/pages/ per singole pagine, come la tua pagina Su di me. Ma, spostare i tuoi articoli del blog fuori da questa cartella speciale ti permetterà di usare API più potenti e performanti per generare il tuo indice di articoli del blog e visualizzare i tuoi singoli articoli del blog.

Allo stesso tempo, riceverai una guida e un autocompletamento migliori nel tuo editor di codice perché avrai uno schema (EN) per definire una struttura comune per ogni articolo che Astro ti aiuterà a far rispettare attraverso Zod, una libreria di dichiarazione e validazione di schemi per TypeScript. Nel tuo schema, puoi specificare quando le proprietà frontmatter sono richieste, come una descrizione o un autore, e quale tipo di dati ogni proprietà deve essere, come una stringa o un array. Questo porta a individuare molti errori prima, con messaggi di errore descrittivi che ti dicono esattamente qual è il problema.

Leggi di più sulle raccolte di contenuti di Astro (EN) nella nostra guida, o inizia con le istruzioni qui sotto per convertire un blog base da src/pages/posts/ a src/blog/.

  1. Quale tipo di pagina probabilmente manterresti in src/pages/?

  2. Quale non è un vantaggio dello spostamento di articoli del blog in una raccolta di contenuti?

  3. Le raccolte di contenuti usano TypeScript …

I passaggi seguenti mostrano come estendere il prodotto finale del tutorial Crea un Blog creando una raccolta di contenuti per gli articoli del blog.

Aggiorna all’ultima versione di Astro e aggiorna tutte le integrazioni alle loro ultime versioni eseguendo i seguenti comandi nel tuo terminale:

Finestra del terminale
# Aggiorna Astro e le integrazioni ufficiali insieme
npx @astrojs/upgrade
  1. Crea una nuova raccolta (cartella) chiamata src/blog/.

  2. Sposta tutti i tuoi articoli del blog esistenti (file .md) da src/pages/posts/ in questa nuova raccolta.

  3. Crea un file src/content.config.ts per definire uno schema (EN) per la tua postsCollection. Per il codice del tutorial del blog esistente, aggiungi i seguenti contenuti al file per definire tutte le proprietà frontmatter usate nei suoi articoli del blog:

    src/content.config.ts
    // Importa il glob loader
    import { glob } from "astro/loaders";
    // Importa utilità da `astro:content`
    import { z, defineCollection } from "astro:content";
    // Definisci un `loader` e uno `schema` per ogni raccolta
    const blog = defineCollection({
    loader: glob({ pattern: '**/[^_]*.md', base: "./src/blog" }),
    schema: z.object({
    title: z.string(),
    pubDate: z.date(),
    description: z.string(),
    author: z.string(),
    image: z.object({
    url: z.string(),
    alt: z.string()
    }),
    tags: z.array(z.string())
    })
    });
    // Esporta un singolo oggetto `collections` per registrare le tue raccolte
    export const collections = { blog };
  4. Affinché Astro riconosca il tuo schema, esci (CTRL + C) e riavvia il server di sviluppo per continuare con il tutorial. Questo definirà il modulo astro:content.

  1. Crea un file pagina chiamato src/pages/posts/[...slug].astro. I tuoi file Markdown e MDX non diventano più automaticamente pagine usando il routing basato su file di Astro quando si trovano all’interno di una raccolta, quindi devi creare una pagina responsabile della generazione di ogni singolo articolo del blog.

  2. Aggiungi il seguente codice per interrogare la tua raccolta (EN) per rendere disponibili lo slug e il contenuto della pagina di ogni articolo del blog a ogni pagina che genererà:

    src/pages/posts/[...slug].astro
    ---
    import { getCollection, render } from 'astro:content';
    export async function getStaticPaths() {
    const posts = await getCollection('blog');
    return posts.map(post => ({
    params: { slug: post.id }, props: { post },
    }));
    }
    const { post } = Astro.props;
    const { Content } = await render(post);
    ---
  3. Renderizza il tuo <Content /> dell’articolo all’interno del layout per pagine Markdown. Questo ti permette di specificare un layout comune per tutti i tuoi articoli.

    src/pages/posts/[...slug].astro
    ---
    import { getCollection, render } from 'astro:content';
    import MarkdownPostLayout from '../../layouts/MarkdownPostLayout.astro';
    export async function getStaticPaths() {
    const posts = await getCollection('blog');
    return posts.map(post => ({
    params: { slug: post.id }, props: { post },
    }));
    }
    const { post } = Astro.props;
    const { Content } = await render(post);
    ---
    <MarkdownPostLayout frontmatter={post.data}>
    <Content />
    </MarkdownPostLayout>
  4. Rimuovi la definizione di layout nel frontmatter di ogni singolo articolo. Il tuo contenuto è ora avvolto in un layout quando viene renderizzato e questa proprietà non è più necessaria.

    src/content/posts/post-1.md
    ---
    layout: ../../layouts/MarkdownPostLayout.astro
    title: 'Il mio primo articolo del blog'
    pubDate: 2022-07-01
    ...
    ---

Sostituisci import.meta.glob() con getCollection()

Sezione intitolata Sostituisci import.meta.glob() con getCollection()
  1. Ovunque tu abbia un elenco di articoli del blog, come la pagina Blog del tutorial (src/pages/blog.astro/), dovrai sostituire import.meta.glob() con getCollection() (EN) come modo per recuperare contenuto e metadata dai tuoi file Markdown.

    src/pages/blog.astro
    ---
    import { getCollection } from "astro:content";
    import BaseLayout from "../layouts/BaseLayout.astro";
    import BlogPost from "../components/BlogPost.astro";
    const pageTitle = "Il mio Blog di apprendimento di Astro";
    const allPosts = Object.values(import.meta.glob("../pages/posts/*.md", { eager: true }));
    const allPosts = await getCollection("blog");
    ---
  2. Dovrai anche aggiornare i riferimenti ai dati restituiti per ogni post. Ora troverai i tuoi valori frontmatter sulla proprietà data di ogni oggetto. Inoltre, quando usi le raccolte, ogni oggetto post avrà uno slug di pagina, non un URL completo.

    src/pages/blog.astro
    ---
    import { getCollection } from "astro:content";
    import BaseLayout from "../layouts/BaseLayout.astro";
    import BlogPost from "../components/BlogPost.astro";
    const pageTitle = "Il mio Blog di apprendimento di Astro";
    const allPosts = await getCollection("blog");
    ---
    <BaseLayout pageTitle={pageTitle}>
    <p>Questo è dove pubblicherò sul mio percorso di apprendimento di Astro.</p>
    <ul>
    {
    allPosts.map((post) => (
    <BlogPost url={post.url} title={post.frontmatter.title} />)}
    <BlogPost url={`/posts/${post.id}/`} title={post.data.title} />
    ))
    }
    </ul>
    </BaseLayout>
  3. Anche la pagina del tutorial blog genera dinamicamente una pagina per ogni tag usando src/pages/tags/[tag].astro e visualizza un elenco di tag su src/pages/tags/index.astro.

    Applica le stesse modifiche di sopra a questi due file:

    • recupera i dati su tutti i tuoi articoli del blog usando getCollection("blog") invece di usare import.meta.glob()
    • accedi a tutti i valori frontmatter usando data invece di frontmatter
    • crea un URL di pagina aggiungendo lo slug dell’articolo al percorso /posts/

    La pagina che genera singole pagine di tag ora diventa:

    src/pages/tags/[tag].astro
    ---
    import { getCollection } from "astro:content";
    import BaseLayout from "../../layouts/BaseLayout.astro";
    import BlogPost from "../../components/BlogPost.astro";
    export async function getStaticPaths() {
    const allPosts = await getCollection("blog");
    const uniqueTags = [...new Set(allPosts.map((post) => post.data.tags).flat())];
    return uniqueTags.map((tag) => {
    const filteredPosts = allPosts.filter((post) =>
    post.data.tags.includes(tag)
    );
    return {
    params: { tag },
    props: { posts: filteredPosts },
    };
    });
    }
    const { tag } = Astro.params;
    const { posts } = Astro.props;
    ---
    <BaseLayout pageTitle={tag}>
    <p>Articoli taggati con {tag}</p>
    <ul>
    { posts.map((post) => <BlogPost url={`/posts/${post.id}/`} title={post.data.title} />) }
    </ul>
    </BaseLayout>

    Prova tu stesso - Aggiorna la query nella pagina Indice di Tag

    Sezione intitolata Prova tu stesso - Aggiorna la query nella pagina Indice di Tag

    Importa e usa getCollection per recuperare i tag usati negli articoli del blog su src/pages/tags/index.astro, seguendo gli stessi passaggi di sopra.

    Mostrami il codice.
    src/pages/tags/index.astro
    ---
    import { getCollection } from "astro:content";
    import BaseLayout from "../../layouts/BaseLayout.astro";
    const allPosts = await getCollection("blog");
    const tags = [...new Set(allPosts.map((post) => post.data.tags).flat())];
    const pageTitle = "Indice di Tag";
    ---
    <!-- ... -->

Aggiorna qualsiasi valore frontmatter per corrispondere al tuo schema

Sezione intitolata Aggiorna qualsiasi valore frontmatter per corrispondere al tuo schema

Se necessario, aggiorna qualsiasi valore frontmatter in tutto il tuo progetto, come nel tuo layout, che non corrisponde allo schema delle tue raccolte.

Nell’esempio del tutorial del blog, pubDate era una stringa. Ora, secondo lo schema che definisce i tipi per il frontmatter dell’articolo, pubDate sarà un oggetto Date. Ora puoi approfittare di questo per usare i metodi disponibili per qualsiasi oggetto Date per formattare la data.

Per renderizzare la data nel layout dell’articolo del blog, convertila in una stringa usando il metodo toLocaleDateString():

src/layouts/MarkdownPostLayout.astro
<!-- ... -->
<BaseLayout pageTitle={frontmatter.title}>
<p>{frontmatter.pubDate.toLocaleDateString()}</p>
<p><em>{frontmatter.description}</em></p>
<p>Scritto da: {frontmatter.author}</p>
<img src={frontmatter.image.url} width="300" alt={frontmatter.image.alt} />
<!-- ... -->

Il progetto del tutorial del blog include un feed RSS. Anche questa funzione deve usare getCollection() per restituire informazioni dai tuoi articoli del blog. Genererai quindi gli item RSS usando l’oggetto data restituito.

src/pages/rss.xml.js
import rss from '@astrojs/rss';
import { pagesGlobToRssItems } from '@astrojs/rss';
import { getCollection } from 'astro:content';
export async function GET(context) {
const posts = await getCollection("blog");
return rss({
title: 'Studente Astro | Blog',
description: 'Il mio percorso di apprendimento di Astro',
site: context.site,
items: await pagesGlobToRssItems(import.meta.glob('./**/*.md')),
items: posts.map((post) => ({
title: post.data.title,
pubDate: post.data.pubDate,
description: post.data.description,
link: `/posts/${post.id}/`,
})),
customData: `<language>it-it</language>`,
})
}

Per l’esempio completo del tutorial del blog che usa raccolte di contenuti, vedi il branch Raccolte di contenuti del repository del tutorial.

Contribuisci Comunità Sponsor