J’ai migré mon blog de Gatsby et React à AstroJS et Preact

J’ai migré mon blog de Gatsby et React à AstroJS et Preact

Astro est principalement un générateur de sites statiques. Il organise la structure de la façon dont tes pages sont générées en HTML une fois, en utilisant des composants, et il se charge ensuite de la création de contenu.

Imagine que tu veux écrire sur ton blog seulement, tu veux générer du contenu statique et après avoir lu diverses opinions sur Internet, ils te recommandent d’apprendre React, Vue, Angular ou quelque nouveau stack que tu ne connais pas. Encore pire, d’utiliser Wordpress.

Parfois, on n’a pas besoin de se compliquer la vie si la seule chose que l’on veut est créer des sites HTML.

En tant que développeur, bien sûr qu’à un moment donné, je pourrais avoir besoin d’utiliser des composants dynamiques. Par exemple, pour obtenir et afficher les deux derniers articles de mon blog.

Mon dernier blog a été écrit sur GatsbyJS, et c’est une migration depuis Wordpress en même temps.

Après quelque temps, créer des pages statiques sur Gatsby a été une bonne option. Cependant, lorsque j’ai voulu développer des fonctionnalités avancées tout en conservant la même structure, cela est devenu complexe. De plus, son API pour retourner des posts en objets imbriqués, je l’appelle le “node hell”, l’enfer des nœuds.

La principale raison derrière cela

Si j’avais d’une seule gros raison pourquoi j’ai choisi Astro, au lieu d’autre framework comme NextJS, qui est très populaire maintenant, c’était car je veux écrire HTML pour mes composants ou pages, et ensuite avoir la disponibilité d’écrire articles en utilisant Markdown, une langage de code soutien utilisé parmi les développeurs. Tu n’as pas besoin de te préoccuper pour faire des clics entre les boutons différents ou d’utiliser raccourcis pour formatter le texte, comme Word.

C’est tout sur la simplicité et la puissance. Lorsque plus de fonctionnalités deviennent faciles avec les plugins, plus de temps je pourrais consacrer à écrire des articles plutôt qu’à réparer.

Seulement pense que Astro utilise son propre format de fichiers : .astro. Même si c’est un nouveau type de format, tu vas t’habituer bientôt, parce que la majorité du code est en HTML avec quelques modifications. Aussi, tu peux mettre du JavaScript ou du TypeScript dans le même fichier et il sera transformé par le bundler à chaque fois.

D’autres motifs additionnels

Ne pas utiliser GraphQL pour un blog simple

Gatsby a une forte dépendance en GraphQL, probablement parce qu’il a été très populaire dès sa première apparition en 2017. Ses queries sont utilisées pour obtenir et travailler sur les structures qui viennent avec le framework.

Par exemple, voici une comparaison pour obtenir les articles par langue en Gatsby.

gatsby-node.ts
const createTagsPage = async (graphql: CreatePagesArgs['graphql'], createPage: Actions['createPage']) => {
const tagTemplate = path.resolve('./src/components/Templates/PostsByTagAndLocale.tsx');
for (const locale of allLanguages) {
const result = await graphql<Queries.AllTagsByLocaleQuery>(
`
query AllTagsByLocale($locale: String!) {
tagsGroup: allMdx(filter: { fields: { locale: { eq: $locale } } }) {
group(field: { frontmatter: { tags: SELECT } }) {
fieldValue
}
}
}
`,
{ locale: locale },
);
const tags = result.data?.tagsGroup.group;
for (const tag of tags) {
createPage({
path: localizeUrl(`/tags/${tag.fieldValue}`, locale),
component: tagTemplate,
context: {
tag: tag.fieldValue,
locale,
tagsForSeo: tags,
},
});
}
}

On peut voir la dépendance sur GraphQL. Pour faire des queries, tu devrais aller à l’outil GraphiQL et les construire là-bas. En Astro, on dépend de JavaScript ou TypeScript seulement.

utils.ts
export const getPostsBy = async ({
language,
limit,
}: {
language: "en" | "es" | "fr" | "pt";
limit?: boolean;
}): Promise<CollectionEntry<"blog">[]> => {
let posts = await getCollection("blog", ({ slug }) => slug.startsWith(`${language}/`));
posts = posts.sort((current, next) => next.data.pubDate.valueOf() - current.data.pubDate.valueOf());
if (limit) {
posts = posts.slice(0, 2);
}
return posts;
};

Et comme Astro génère les types en démarrant le serveur, on a l’autocomplétion disponible. Gatsby les génère aussi, mais avec la mise en garde que cela prend plus de temps pour démarrer le serveur de développement.

Support pour TypeScript

Gatsby a un bon support pour TypeScript, mais dès que tu veux une nouvelle façon de travailler et de typer les nœuds, cela peut devenir compliqué. Astro, dans son propre type de fichier, peut travailler avec TypeScript.

À quel point veux-tu devenir plus stricte dans la configuration ? Ça dépend de toi. Astro donne l’option de choisir le niveau de rigueur des types.

Voici un exemple de comment, pour faire un bouton comme composant, je spécifie ses types dans un fichier .astro.

---
import { icon } from "@fortawesome/fontawesome-svg-core";
import { faAppStore, faGooglePlay } from "@fortawesome/free-brands-svg-icons";
const faAppStoreIcon = icon(faAppStore).html[0] as string;
const faGooglePlayIcon = icon(faGooglePlay).html[0] as string;
type Props = {
title: string;
link: string;
isAppleApp: boolean;
};
const { link, title, isAppleApp } = Astro.props;
---
<a
href={link}
target="_blank"
class="inline-flex rounded-full px-5 py-3 items-center mr-2 bg-black text-white dark:bg-gray-700 dark:text-white"
>
<Fragment set:html={isAppleApp ? faAppStoreIcon : faGooglePlayIcon} />
<span class="ml-3 font-semibold font-quicksand">{title}</span>
</a>

Pour obtenir plus d’informations sur la configuration de TypeScript dans Astro, regarde le lien ici .

Temps de développement et de déploiement plus rapides

Je me souviens de chaque fois où j’ai voulu commencer à travailler sur mon environnement local de Gatsby. Ça a pris plus d’une minute dès que j’ai exécuté la commande, et pour moins de 40 pages, ça n’avait aucun sens. Et si je voulais installer un nouveau package de NPM et redémarrer le serveur ? Et si je laisse le code sans finir et que l’autosauvegarde s’exécute et que mon serveur de développement s’arrête ? Encore une autre minute pour commencer à coder ou à écrire.

De plus, Gatsby a un temps de construction des pages plus long. Mes derniers déploiements sur Vercel montrent un temps moyen de 2 minutes. Encore pire, Gatsby propose des déploiements incrémentaux (incremental deployments), qui construisent uniquement les fichiers modifiés, au lieu d’améliorer les temps de construction. Une déception.

Avec Astro, générer 40 pages et démarrer le serveur est instantané, en moins de 10 secondes. Pour les déploiements, cela prend la moitié du temps, soit 50 secondes en novembre 2023.

Compatibilité avec divers frameworks

Si tu as quelques plugins qui fonctionnent seulement dans des frameworks spécifiques comme React, Astro te donne la chance de les continuer à utiliser. Donc, tu peux garder la fonctionnalité que tu ne veux pas programmer depuis zéro.

En général, je recommanderais de n’utiliser aucun framework frontend sauf si nécessaire, car ils ajoutent de la taille au fichier final, ce qui augmente les temps de chargement de ta page. L’objectif d’Astro est de garder une exécution totalement légère.

Excellente documentation

Astro, tout comme Laravel, mon framework préféré, a une documentation claire qui montre les tutoriels les plus courants pour créer des sites web statiques. Il prend en charge l’ajout de syntaxes de code, le support de plusieurs langues, et permet d’activer MDX pour tes publications, etc.

Facilité de modification des balises SEO

Chaque composant Astro utilise la syntaxe HTML. Tu peux utiliser tous les tags HTML, même <html>. Si tu veux inclure quelque chose dans ton <header>, comme les tags utilisés pour le SEO, le titre de la page et similaires, il est facile de l’écrire sans utiliser des composants additionnels. Bien sûr, pour plus de commodité, il est préférable d’extraire ton <header> comme composant.

Support pour l’hébergement

Astro, en générant HTML, est compatible avec cent des serveurs d’hébergement sur le marché, y compris certains gratuits. J’ai choisi Vercel, car il offre des déploiements par branch et par commit.

Mon expérience en migration de framework

Il est important de noter que je n’ai pas commencé à migrer mon site de Gatsby à Astro le premier jour. Ce que je voulais savoir, c’est quelles sont les similitudes ou à quel point il est difficile de mettre en œuvre certaines fonctionnalités que j’avais dans mon blog Gatsby.

La vérité sur la migration vers Astro est que ce n’est pas aussi difficile que je le pensais au début. Astro est livré avec divers outils et j’ai suivi ses tutoriels pour créer un blog.

Mon expérience en utilisant Frontmatter m’a beaucoup aidé, mais j’ai effectué pas des configurations compliquées dessus.

Voici les étapes que j’ai utilisées pour migrer vers Astro.

Étapes pour vérifier la migration de Gatsby vers Astro

  1. Installer le projet basé sur le template du blog. Il résout quelques problèmes, par exemple, la génération de plusieurs pages par slug.
  2. Ajouter Tailwind, qui a un support officiel pour Astro en suivant quelques étapes.
  3. Faire un setup de Frontmatter et habiliter MDX.
  4. Créer une structure de fichiers et de pages pour ajouter le support multilingue, avec des préfixes d’URL qui commencent par la langue spécifique. Par exemple, /blog et /es/blog.
  5. Lister les publications par langue. Pour le faire, chaque fichier est dans le dossier qui a un préfixe avec les deux premières lettres de la langue.
  6. Vérifier que l’on peut ajouter le support pour le thème sombre et clair. Je l’ai eu en combinant le localStorage de JavaScript avec un composant Astro.
  7. Vérifier que ma page principale peut obtenir les deux derniers posts par jour de la publication.
  8. Attribuer une liste de hashtags pour chaque publication, puis obtenir tous les hashtags et générer une nouvelle page pour chacun. Cette page répertorie toutes les publications dans une langue spécifique qui contiennent le hashtag mentionné.
  9. J’ai vérifié que les slugs dans les URL des publications sont identiques, afin d’éviter de perdre l’indexation de Google.
  10. Créer une barre de recherche qui me permet de trouver mes posts selon le titre ou la description.
  11. En développant toutes les étapes précédentes, j’ai migré l’UI complète, y compris les classes et les styles.
  12. Faire une migration depuis React et optimiser avec Preact.
  13. Améliorations de SEO, en ajoutant des titres et en fixant les titres et les descriptions.
  14. Déploiement sur Vercel et premiers tests. Lorsque j’ai eu une version à 80% des caractéristiques de mon dernier blog, je l’ai déployée en production.

Quelques difficultés apparaissent

Ensuite, quelques fonctionnalités plus difficiles pour migrer vers Astro.

Migration de FontAwesome

Les icônes de FontAwesome ont été l’une des caractéristiques les plus compliquées à déplacer, car il y a des bugs de compatibilité entre Astro et les SVG des icônes.

Lorsque tu utilises Gatsby ou un autre framework basé sur React, tu aurais besoin d’importer la bibliothèque @fortawesome/react-fontawesome. Dans Astro, tu n’en as pas besoin.

Terminal window
# Installer la bibliothèque principale
npm i --save @fortawesome/fontawesome-svg-core
# Installes des icônes gratuites
npm i --save @fortawesome/free-solid-svg-icons
npm i --save @fortawesome/free-regular-svg-icons
npm i --save @fortawesome/free-brands-svg-icons

Dans un composant Astro, importe les icônes dont tu as besoin. Je vais mettre un code similaire à ce que j’ai fait pour le footer de cette page.

---
import { icon } from "@fortawesome/fontawesome-svg-core";
import { faGithub, faLinkedin } from "@fortawesome/free-brands-svg-icons";
---

Après, utilise la fonction icon du cœur pour générer le SVG.

---
import { icon } from "@fortawesome/fontawesome-svg-core";
import { faGithub, faLinkedin } from "@fortawesome/free-brands-svg-icons";
const faLinkedinIcon = icon(faLinkedin).html[0];
const faGithubIcon = icon(faGithub).html[0];
---

Pendant que les SVG sont sauvegardés dans une nouvelle variable, ils sont combinés avec le composant Fragment d’Astro. Ce composant ne doit pas être importé avec le même nom que celui utilisé par React. Et passe le SVG à sa propriété set:html.

---
import { icon } from "@fortawesome/fontawesome-svg-core";
import { faGithub, faLinkedin } from "@fortawesome/free-brands-svg-icons";
const faLinkedinIcon = icon(faLinkedin).html[0];
const faGithubIcon = icon(faGithub).html[0];
---
<footer class="bg-black dark:bg-gray-800">
<div class="container flex flex-col items-center py-6 mx-auto">
<Fragment set:html={faLinkedinIcon} />
<Fragment set:html={faGithubIcon} />
</div>
</footer>

L’icône s’affiche maintenant sans problème. Si tu veux lui ajouter du style, inclus le Fragment dans un autre composant HTML et ajoute les classes ou les styles là-bas.

Composants Astro vs Composants React

Les composants Astro sont très similaires aux composants React. Pour la migration, j’ai appris comment envoyer les propriétés et conserver le type. Voici un exemple de mon composant Astro, qui est un bouton dont l’icône change en fonction d’une variable booléenne que nous envoyons.

---
import { icon } from "@fortawesome/fontawesome-svg-core";
import { faAppStore, faGooglePlay } from "@fortawesome/free-brands-svg-icons";
const faAppStoreIcon = icon(faAppStore).html[0] as string;
const faGooglePlayIcon = icon(faGooglePlay).html[0] as string;
type Props = {
title: string;
link: string;
isAppleApp: boolean;
};
const { link, title, isAppleApp } = Astro.props;
---
<a
href={link}
target="_blank"
class="inline-flex rounded-full px-5 py-3 items-center mr-2 bg-black text-white dark:bg-gray-700 dark:text-white"
>
<Fragment set:html={isAppleApp ? faAppStoreIcon : faGooglePlayIcon} />
<span class="ml-3 font-semibold font-quicksand">{title}</span>
</a>

Observez comment je spécifie dans le framework que j’ai besoin de trois propriétés : const { link, title, isAppleApp } = Astro.props;

Astro ne doit pas être importé, il est disponible globalement.

Ensuite, pour avoir un typage fort, on a le type Props, on lui assigne les types des variables qui ont été écrites dans les Astro.props requis.

type Props = {
title: string;
link: string;
isAppleApp: boolean;
};

Plugins de React et utilisation de React

À cause de deux composants que je conserve sur mon site, j’ai besoin d’utiliser déjà React. Cependant, il y a une version plus légère qui a une grande chance d’exécuter tes plugins React. On parle de Preact, un framework minimaliste qui est basé sur la syntaxe de React et qui est fier d’avoir un poids de 3KB.

Pour obtenir plus d’informations sur React, suivez ce lien .

Preact s’intègre avec Astro en quelques étapes, comme tu peux le voir dans ce lien , il vient aussi avec le support compat. C’est ce que j’ai activé pour continuer l’utilisation du plugin Typing Animation , qui reste sur ma page principale.

On doit être conscient du typage des événements dans Preact, car ils ne sont pas les mêmes que dans React. Voici une démo de ma barre de recherche, qui est l’un des composants implémentés en React.

search.tsx
const SearchBar = (props: {
searchQuery: string;
setSearchQuery: (value: string) => void;
typeAndPressEnterText: string;
}) => {
const handleInputChange = (event: Event) => {
props.setSearchQuery((event.target as HTMLInputElement).value);
};
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Enter") {
props.setSearchQuery(props.searchQuery);
}
};
return (
<section className="w-full mt-9">
<input
id="search-input"
type="text"
placeholder={props.typeAndPressEnterText}
className="w-full py-5 px-4 text-2xl bg-white border-2 rounded-md shadow-sm dark:bg-gray-800 dark:border-gray-900 caret-blue-200 dark:text-white font-quicksand"
onInput={handleInputChange}
onKeyDown={handleKeyDown}
value={props.searchQuery}
/>
</section>
);
};

Regarde les lignes surlignées, leurs typages sont les mêmes que React. On voit aussi qu’au lieu d’utiliser onChange, on utilise onInput, car c’est une implémentation recommandée par React lui-même.

Support pour le thème clair et sombre en utilisant Tailwind et Astro

Dans mon dernier blog Gatsby, j’ai eu du support pour changer entre le mode clair et sombre. L’inconvénient est qu’il utilise beaucoup les contextes de React. Alors, en migrant plusieurs de mes composants de React à Astro, j’ai commencé à penser à d’autres options. Aussi, j’ai lu il y a deux mois que Tailwind facilite beaucoup l’utilisation de classes pour les deux modes.

Ensuite, je montre comment le composant Astro est fini, qui utilise le localStorage du navigateur pour sauvegarder les préférences d’utilisateur.

ThemeToggle.astro
<section id="themetoggle" class="hover:cursor-pointer text-xl">
<span id="themetoggle_moon" class="hidden text-black"> </span>
<span id="themetoggle_sun" class="hidden text-white"> </span>
</section>
<script>
import { icon } from "@fortawesome/fontawesome-svg-core";
import { faMoon, faSun } from "@helmerdavila/fontawesomehelmer/standalone/pro-duotone-svg-icons";
const loadTheme = () => {
const theme = localStorage.getItem("theme") ?? "light";
// Cacher ou afficher l'icône du soleil ou de la lune en fonction du thème actuel
if (theme === "dark") {
document.documentElement.classList.add("dark");
document.querySelector("#themetoggle_sun")?.classList.remove("hidden");
} else {
document.documentElement.classList.remove("dark");
document.querySelector("#themetoggle_moon")?.classList.remove("hidden");
}
};
const loadIcons = () => {
// Chargement des icônes depuis FontAwesome
const faMoonIcon = icon(faMoon).html[0] as string;
const faSunIcon = icon(faSun).html[0] as string;
const spanIconMoon = document.getElementById("themetoggle_moon") as HTMLElement;
const spanIconSun = document.getElementById("themetoggle_sun") as HTMLElement;
spanIconMoon.innerHTML = faMoonIcon;
spanIconSun.innerHTML = faSunIcon;
};
// Ajout de l'événement de changement de thème lorsque l'utilisateur clique sur la section avec l'ID themetoggle
document.getElementById("themetoggle")?.addEventListener("click", () => {
const theme = localStorage.getItem("theme") ?? "light";
const nowUseTheme = theme === "light" ? "dark" : "light";
localStorage.setItem("theme", nowUseTheme);
window.location.reload();
});
// Lorsque le DOM est chargé, charger le thème et les icônes
window.addEventListener("load", () => {
loadTheme();
loadIcons();
});
</script>

Conclusions

Au moment où j’écris ce post, mon blog a plus de deux mois sur Astro. Je pense que je ne me suis jamais senti aussi à l’aise et productif en travaillant sur un outil de création de pages web avec une documentation claire et qui s’exécute rapidement sur mon serveur de développement. De plus, j’aime le fait qu’ajouter des améliorations soit très facile et que tout cela soit documenté sur son site officiel, sans avoir besoin de vérifier d’autres sources d’information ou de visiter Github pour parcourir les commentaires et trouver la solution aux problèmes les plus courants que tout développeur peut rencontrer avec ces frameworks.

Mes articles ne sont pas generés par l'IA, cependant ils pourrait y être corrigés. Le premier brouillon est ma création originale

Tags

Auteur

Écrit par Helmer Davila

Dans d'autres langues

Astro is primarily a static site generator. It allows you to structure your site however you want and generate HTML pages only once, using components.

Why and how I moved my blog away from Gatsby and React to Astro Js and Preact

Astro es un generador de sitios estáticos principalmente. Ordena la estructura de cómo quieres que tus páginas se generen en HTML una vez, usando componentes, y dedícate después a crear contenido.

Porqué y cómo moví mi blog de Gatsby con React a Astro JS y Preact