Astro pour les développeurs WordPress

Sur cette page

Astro est un framework web pour créer des sites web axés sur le contenu. Lors de l’utilisation d’EmDash, Astro remplace votre thème WordPress — il gère le templating, le routage et le rendu.

Ce guide enseigne les fondamentaux d’Astro en les associant aux concepts WordPress que vous comprenez déjà.

Changements de paradigme clés

Rendu côté serveur par défaut

Comme PHP, le code Astro s’exécute sur le serveur. Contrairement à PHP, il génère du HTML statique par défaut avec zéro JavaScript.

Zéro JS sauf si vous l'ajoutez

WordPress charge jQuery et les scripts de thème automatiquement. Astro ne livre rien au navigateur sauf si vous l’ajoutez explicitement.

Architecture basée sur les composants

Au lieu de balises de template dispersées et d’includes, construisez avec des composants composables et autonomes.

Routage basé sur les fichiers

Pas de règles de réécriture ou de query_vars. La structure de fichiers dans src/pages/ définit vos URLs directement.

Structure du projet

Les thèmes WordPress ont une structure plate avec des noms de fichiers magiques. Astro utilise des répertoires explicites :

WordPressAstroObjectif
index.php, single.phpsrc/pages/Routes (URLs)
template-parts/src/components/Éléments d’UI réutilisables
header.php + footer.phpsrc/layouts/Enveloppes de page
style.csssrc/styles/CSS global
functions.phpastro.config.mjsConfiguration du site

L’arborescence suivante montre une disposition typique de projet Astro :

src/
├── components/        # Reusable UI (Header, PostCard, etc.)
├── layouts/           # Page shells (Base.astro)
├── pages/             # Routes - files become URLs
│   ├── index.astro    # → /
│   ├── posts/
│   │   ├── index.astro      # → /posts
│   │   └── [slug].astro     # → /posts/hello-world
│   └── [slug].astro   # → /about, /contact, etc.
└── styles/
    └── global.css

Composants Astro

Les fichiers .astro sont l’équivalent Astro des templates PHP. Chaque fichier comporte deux parties :

  1. Frontmatter (entre les délimiteurs ---) — Code côté serveur, comme PHP en haut d’un template
  2. Template — HTML avec expressions, comme le reste d’un template PHP

Le composant suivant déclare des props typés dans le frontmatter et les rend dans le template :

---
// Frontmatter: runs on server, never sent to browser
interface Props {
  title: string;
  excerpt: string;
  url: string;
}

const { title, excerpt, url } = Astro.props;
---
<!-- Template: outputs HTML -->
<article class="post-card">
  <h2><a href={url}>{title}</a></h2>
  <p>{excerpt}</p>
</article>

Différences clés avec PHP :

  • Le frontmatter est isolé. Les variables déclarées là sont disponibles dans le template, mais le code lui-même n’atteint jamais le navigateur.
  • Les imports vont dans le frontmatter. Composants, données, utilitaires — tout est importé en haut.
  • TypeScript fonctionne. Définissez les types de props avec interface Props pour l’autocomplétion de l’éditeur et la validation.

Expressions de template

Les templates Astro utilisent des {accolades} au lieu de balises <?php ?>. La syntaxe est similaire à JSX mais génère du HTML pur.

Astro

---
import { getEmDashCollection } from "emdash";

const { entries: posts } = await getEmDashCollection("posts");
const showTitle = true;
---
{showTitle && <h1>Latest Posts</h1>}

{posts.length > 0 ? (
  <ul>
    {posts.map(post => (
      <li>
        <a href={`/posts/${post.id}`}>{post.data.title}</a>
      </li>
    ))}
  </ul>
) : (
  <p>No posts found.</p>
)}

PHP

<?php
$posts = new WP_Query(['post_type' => 'post']);
$show_title = true;
?>

<?php if ($show_title): ?>
  <h1>Latest Posts</h1>
<?php endif; ?>

<?php if ($posts->have_posts()): ?>
  <ul>
    <?php while ($posts->have_posts()): $posts->the_post(); ?>
      <li>
        <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
      </li>
    <?php endwhile; wp_reset_postdata(); ?>
  </ul>
<?php else: ?>
  <p>No posts found.</p>
<?php endif; ?>

Modèles d’expression

ModèleObjectif
{variable}Afficher une valeur
{condition && <Element />}Rendu conditionnel
{condition ? <A /> : <B />}If/else
{items.map(item => <Li>{item}</Li>)}Boucles

Props et Slots

Les composants reçoivent des données via des props (comme des arguments de fonction) et des slots (comme des points d’insertion do_action).

Astro

---
interface Props {
  title: string;
  featured?: boolean;
}

const { title, featured = false } = Astro.props;
---
<article class:list={["card", { featured }]}>
  <h2>{title}</h2>
  <slot />
  <slot name="footer" />
</article>

Le balisage suivant utilise ce composant, en passant le slot par défaut et un slot footer nommé :

<Card title="Hello" featured>
  <p>This goes in the default slot.</p>
  <footer slot="footer">Footer content</footer>
</Card>

PHP

<?php
// Usage: get_template_part('template-parts/card', null, [
//   'title' => 'Hello',
//   'featured' => true
// ]);

$title = $args['title'] ?? '';
$featured = $args['featured'] ?? false;
$class = $featured ? 'card featured' : 'card';
?>
<article class="<?php echo esc_attr($class); ?>">
  <h2><?php echo esc_html($title); ?></h2>
  <?php
  // No direct equivalent to slots.
  // WordPress uses do_action() for similar patterns:
  do_action('card_content');
  do_action('card_footer');
  ?>
</article>

Props vs $args

Dans WordPress, get_template_part() passe les données via le tableau $args. Les props Astro sont typés et déstructurés :

---
// Type-safe with defaults
interface Props {
  title: string;
  count?: number;
}
const { title, count = 10 } = Astro.props;
---

Slots vs Hooks

WordPress utilise do_action() pour créer des points d’insertion. Astro utilise des slots :

WordPressAstro
do_action('before_content')<slot name="before" />
Zone de contenu par défaut<slot />
do_action('after_content')<slot name="after" />

La différence : les slots reçoivent des éléments enfants sur le site d’appel, tandis que les hooks WordPress nécessitent des appels add_action() séparés ailleurs.

Layouts

Les layouts enveloppent les pages avec une structure HTML commune — le <head>, l’en-tête, le pied de page et tout ce qui est partagé entre les pages. Cela remplace header.php + footer.php. Le layout suivant définit cette enveloppe partagée et expose un slot pour le contenu de la page :

---
import "../styles/global.css";

interface Props {
  title: string;
  description?: string;
}

const { title, description = "My EmDash Site" } = Astro.props;
---
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content={description} />
    <title>{title}</title>
  </head>
  <body>
    <header>
      <nav><!-- Navigation --></nav>
    </header>

    <main>
      <slot />
    </main>

    <footer>
      <p>&copy; {new Date().getFullYear()}</p>
    </footer>
  </body>
</html>

Utilisez le layout dans une page :

---
import Base from "../layouts/Base.astro";
---
<Base title="Home">
  <h1>Welcome</h1>
  <p>Page content goes in the slot.</p>
</Base>

Stylisation

Astro offre plusieurs approches de stylisation. La plus distinctive sont les styles scopés.

Styles scopés

Les styles dans une balise <style> sont automatiquement scopés à ce composant :

<article class="card">
  <h2>Title</h2>
</article>

<style>
  /* Only affects .card in THIS component */
  .card {
    padding: 1rem;
    border: 1px solid #ddd;
  }

  h2 {
    color: navy;
  }
</style>

Le HTML généré inclut des noms de classe uniques pour empêcher la fuite de styles, de sorte que les styles des composants restent contenus sans escalader la spécificité du sélecteur.

Styles globaux

Pour les styles à l’échelle du site, créez un fichier CSS et importez-le dans un layout :

---
import "../styles/global.css";
---

Classes conditionnelles

La directive class:list remplace la construction manuelle de chaînes de classe :

Astro

---
const { featured, size = "medium" } = Astro.props;
---
<article class:list={[
  "card",
  size,
  { featured, "has-border": true }
]}>

Sortie : <article class="card medium featured has-border">

PHP

<?php
$classes = ['card', $size];
if ($featured) $classes[] = 'featured';
if (true) $classes[] = 'has-border';
?>
<article class="<?php echo esc_attr(implode(' ', $classes)); ?>">

JavaScript côté client

Astro livre zéro JavaScript par défaut. C’est le plus grand changement mental par rapport à WordPress.

Ajout d’interactivité

Pour des interactions simples, ajoutez une balise <script> :

<button id="menu-toggle">Menu</button>
<nav id="mobile-menu" hidden>
  <slot />
</nav>

<script>
  const toggle = document.getElementById("menu-toggle");
  const menu = document.getElementById("mobile-menu");

  toggle?.addEventListener("click", () => {
    menu?.toggleAttribute("hidden");
  });
</script>

Les scripts sont automatiquement regroupés et dédupliqués. Si ce composant apparaît deux fois sur une page, le script s’exécute une fois.

Composants interactifs avancés

Pour une interactivité plus complexe, Astro peut charger des composants JavaScript (React, Vue, Svelte) à la demande. C’est optionnel — la plupart des sites fonctionnent bien avec juste des balises <script>. La page suivante charge un composant uniquement lorsqu’il défile dans la vue :

---
import SearchWidget from "../components/SearchWidget.jsx";
---
<!-- Only load JavaScript when the search box scrolls into view -->
<SearchWidget client:visible />
DirectiveQuand JavaScript se charge
client:loadImmédiatement au chargement de la page
client:visibleQuand le composant entre dans le viewport
client:idleQuand le navigateur est inactif

Routage

Astro utilise le routage basé sur les fichiers. Les fichiers dans src/pages/ deviennent des URLs :

FichierURL
src/pages/index.astro/
src/pages/about.astro/about
src/pages/posts/index.astro/posts
src/pages/posts/[slug].astro/posts/hello-world
src/pages/[...slug].astroTout chemin (catch-all)

Routes dynamiques

Pour le contenu CMS, utilisez la syntaxe entre crochets pour les segments dynamiques :

---
import { getEmDashCollection, getEmDashEntry } from "emdash";
import Base from "../../layouts/Base.astro";
import { PortableText } from "emdash/ui";

// For static builds, define which pages to generate
export async function getStaticPaths() {
  const { entries: posts } = await getEmDashCollection("posts");
  return posts.map(post => ({
    params: { slug: post.id },
    props: { post },
  }));
}

const { post } = Astro.props;
---
<Base title={post.data.title}>
  <article>
    <h1>{post.data.title}</h1>
    <PortableText value={post.data.content} />
  </article>
</Base>

Comparé à WordPress

WordPressAstro
Hiérarchie de templates (single-post.php)Fichier explicite : posts/[slug].astro
Règles de réécriture + query_varsStructure de fichiers
$wp_query détermine le templateURL mappe directement au fichier
add_rewrite_rule()Créer des fichiers ou des dossiers

Où vivent les concepts WordPress

Une référence pour trouver l’équivalent Astro/EmDash des fonctionnalités WordPress :

Templating

WordPressAstro/EmDash
Hiérarchie de templatesRoutage basé sur les fichiers dans src/pages/
get_template_part()Importer et utiliser des composants
the_content()<PortableText value={content} />
the_title(), the_*()Accès via post.data.title
Balises de templateExpressions de template {value}
body_class()Directive class:list

Données et requêtes

WordPressAstro/EmDash
WP_QuerygetEmDashCollection(type, filters)
get_post()getEmDashEntry(type, id)
get_posts()getEmDashCollection(type)
get_the_terms()Accès via entry.data.categories
get_post_meta()Accès via entry.data.fieldName
get_option()getSiteSettings()
wp_nav_menu()getMenu(location)

Extensibilité

WordPressAstro/EmDash
add_action()Hooks EmDash, middleware Astro
add_filter()Hooks EmDash
add_shortcode()Blocs personnalisés Portable Text
register_block_type()Blocs personnalisés Portable Text
register_sidebar()Zones de widgets EmDash
PluginsIntégrations Astro + plugins EmDash

Types de contenu

WordPressAstro/EmDash
register_post_type()Créer une collection dans l’UI admin
register_taxonomy()Créer une taxonomie dans l’UI admin
register_meta()Ajouter un champ au schéma de collection
Statut de postStatut d’entrée (draft, published, etc.)
Image mise en avantChamp de référence média
Blocs GutenbergBlocs Portable Text

Mappage des concepts

Les principaux changements de WordPress à Astro couverts dans ce guide :

  • Les templates PHP deviennent des composants Astro : code serveur plus HTML, avec une organisation de fichiers explicite.
  • Les balises de template deviennent des props et des imports : les données transitent par des arguments plutôt que par des globales.
  • Les fichiers de thème deviennent un répertoire de pages : les URLs correspondent à la structure de fichiers.
  • Les hooks deviennent des slots et du middleware : les points d’insertion sont définis là où le contenu est passé.
  • jQuery se charge par défaut dans WordPress ; Astro ne livre pas de JavaScript tant que vous ne l’ajoutez pas.

Commencez avec le guide Getting Started pour créer votre premier site EmDash, ou explorez Working with Content pour apprendre à interroger et rendre des données CMS.