EmDash fornisce funzioni di query per recuperare i contenuti nelle tue pagine e componenti Astro. Queste funzioni seguono il pattern delle collezioni di contenuti live di Astro, restituendo risultati strutturati con gestione degli errori.
Funzioni di query
EmDash esporta due funzioni di query principali:
| Funzione | Scopo | Restituisce |
|---|---|---|
getEmDashCollection | Recuperare tutte le voci di un tipo di contenuto | { entries, error } |
getEmDashEntry | Recuperare una singola voce per ID o slug | { entry, error, isPreview } |
Importale da emdash:
import { getEmDashCollection, getEmDashEntry } from "emdash";
Ottenere tutte le voci
Usa getEmDashCollection per recuperare tutte le voci di un tipo di contenuto:
---
import { getEmDashCollection } from "emdash";
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
console.error("Errore nel caricamento dei post:", error);
}
---
<ul>
{posts.map((post) => (
<li>{post.data.title}</li>
))}
</ul>
Filtrare per locale
Quando l’i18n è abilitato, filtra per locale per recuperare i contenuti in una lingua specifica:
// Post in francese
const { entries: frenchPosts } = await getEmDashCollection("posts", {
locale: "fr",
status: "published",
});
// Usare la locale della richiesta corrente
const { entries: localizedPosts } = await getEmDashCollection("posts", {
locale: Astro.currentLocale,
status: "published",
});
Per voci singole, passa locale come terzo argomento:
const { entry: post } = await getEmDashEntry("posts", "my-post", {
locale: Astro.currentLocale,
});
Quando locale viene omesso, di default usa la locale corrente della richiesta. Se non esiste una traduzione per la locale richiesta, viene seguita la catena di fallback.
Filtrare per stato
Recuperare solo contenuti pubblicati o bozze:
// Solo post pubblicati
const { entries: published } = await getEmDashCollection("posts", {
status: "published",
});
// Solo bozze
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});
Limitare i risultati
Limitare il numero di voci restituite:
// Ottenere i 5 post più recenti
const { entries: recentPosts } = await getEmDashCollection("posts", {
status: "published",
limit: 5,
});
Filtrare per tassonomia
Filtrare le voci per categoria, tag o termini di tassonomia personalizzati:
// Post nella categoria "news"
const { entries: newsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { category: "news" },
});
// Post con il tag "javascript"
const { entries: jsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { tag: "javascript" },
});
// Post che corrispondono a uno qualsiasi di più termini
const { entries: featuredNews } = await getEmDashCollection("posts", {
status: "published",
where: { category: ["news", "featured"] },
});
Il filtro where usa la logica OR quando vengono forniti più valori per una singola tassonomia.
Gestione degli errori
Controlla sempre gli errori quando l’affidabilità è importante:
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
// Registrare e gestire elegantemente
console.error("Errore nel caricamento dei post:", error);
return new Response("Errore del server", { status: 500 });
}
Ottenere una singola voce
Usa getEmDashEntry per recuperare una voce per il suo ID o slug:
---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
const { slug } = Astro.params;
const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Errore del server", { status: 500 });
}
if (!post) {
return Astro.redirect("/404");
}
---
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
Tipo di ritorno della voce
getEmDashEntry restituisce un oggetto risultato:
interface EntryResult<T> {
entry: ContentEntry<T> | null; // null se non trovato
error?: Error; // Impostato solo per errori reali (non "non trovato")
isPreview: boolean; // true se si visualizza anteprima/contenuto bozza
}
interface ContentEntry<T> {
id: string;
data: T;
edit: EditProxy; // Annotazioni di modifica visuale
}
L’oggetto data all’interno di entry contiene tutti i campi definiti per il tipo di contenuto. Il proxy edit fornisce annotazioni di modifica visuale (vedi sotto).
Modalità anteprima
EmDash gestisce l’anteprima automaticamente tramite middleware. Quando un URL contiene un token _preview valido, il middleware lo verifica e configura il contesto della richiesta. Le tue funzioni di query servono quindi contenuti bozza senza parametri speciali:
---
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
// Non è necessaria una gestione speciale dell'anteprima — il middleware lo fa automaticamente
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Errore del server", { status: 500 });
}
if (!entry) {
return Astro.redirect("/404");
}
---
{isPreview && (
<div class="preview-banner">
Visualizzazione anteprima. Questo contenuto non è pubblicato.
</div>
)}
<article>
<h1>{entry.data.title}</h1>
<PortableText value={entry.data.content} />
</article>
Modifica visuale
Ogni voce restituita dalle funzioni di query include un proxy edit per annotare i tuoi template. Espandilo sugli elementi per abilitare la modifica inline per gli editor autenticati:
<article {...entry.edit}>
<h1 {...entry.edit.title}>{entry.data.title}</h1>
<div {...entry.edit.content}>
<PortableText value={entry.data.content} />
</div>
</article>
In modalità modifica, {...entry.edit.title} produce un attributo data-emdash-ref che la barra degli strumenti di modifica visuale usa per abilitare la modifica inline. In produzione, gli spread del proxy non producono output.
Ordinare i risultati
getEmDashCollection non garantisce l’ordine di ordinamento. Ordina i risultati nel tuo template:
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// Ordinare per data di pubblicazione, più recenti per primi
const sorted = posts.sort(
(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0),
);
Modelli di ordinamento comuni
// Alfabetico per titolo
posts.sort((a, b) => a.data.title.localeCompare(b.data.title));
// Per campo di ordinamento personalizzato
posts.sort((a, b) => (a.data.order ?? 0) - (b.data.order ?? 0));
// Ordine casuale
posts.sort(() => Math.random() - 0.5);
Tipi TypeScript
Genera tipi TypeScript per le tue collezioni:
npx emdash types
Questo crea .emdash/types.ts con interfacce per ogni collezione. Usale per la sicurezza dei tipi:
import { getEmDashCollection, getEmDashEntry } from "emdash";
import type { Post } from "../.emdash/types";
// Query di collezione con sicurezza dei tipi
const { entries: posts } = await getEmDashCollection<Post>("posts");
// posts è ContentEntry<Post>[]
// Query di voce con sicurezza dei tipi
const { entry: post } = await getEmDashEntry<Post>("posts", "my-post");
// post è ContentEntry<Post> | null
Rendering statico vs. server
I contenuti EmDash funzionano sia con pagine statiche che renderizzate lato server.
Statico (Pre-renderizzato)
Per le pagine statiche, usa getStaticPaths per generare rotte al momento della build:
---
import { getEmDashCollection, getEmDashEntry } from "emdash";
export async function getStaticPaths() {
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
return posts.map((post) => ({
params: { slug: post.data.slug },
}));
}
const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
---
Renderizzato lato server
Per le pagine renderizzate lato server, interroga i contenuti direttamente:
---
export const prerender = false;
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Errore del server", { status: 500 });
}
if (!post) {
return new Response(null, { status: 404 });
}
---
Considerazioni sulle prestazioni
Caching
EmDash usa le collezioni di contenuti live di Astro, che gestiscono automaticamente il caching. Per le pagine renderizzate lato server, considera l’aggiunta di header di cache HTTP:
---
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// Cache per 5 minuti
Astro.response.headers.set("Cache-Control", "public, max-age=300");
---
Evitare query ridondanti
Interroga una volta e passa i dati ai componenti:
---
import { getEmDashCollection } from "emdash";
import PostList from "../components/PostList.astro";
import Sidebar from "../components/Sidebar.astro";
// Interroga una volta
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
const featured = posts.filter((p) => p.data.featured);
const recent = posts.slice(0, 5);
---
<PostList posts={featured} />
<Sidebar posts={recent} />
Prossimi passi
- Creare un blog - Costruire un blog completo
- Tassonomie - Filtrare per categorie e tag
- Lavorare con i contenuti - Operazioni CRUD dell’admin
- Internazionalizzazione - Contenuti multilingue e traduzioni