Un sandwich 11ty, Vite et JAM —

En janvier 2020, Ben Holmes a entrepris de faire ce que presque tous les développeurs Web font chaque année : reconstruire son site personnel. Dans cet article, il raconte comment il a entrepris de construire son propre pipeline de construction à partir du zéro absolu et a créé Slinkity.
Je ne sais pas pour vous, mais j'ai été submergé par tous les outils de développement Web dont nous disposons ces jours-ci. Que vous aimiez Markdown, HTML simple, React, Vue, Svelte, les modèles Pug, Handlebars, Vibranium – vous pouvez probablement le mélanger avec des données CMS et obtenir un bon cocktail de site statique.
Je ne vais pas vous le dire. quels outils de développement d'interface utilisateur utiliser, car ils sont tous excellents, en fonction des besoins de votre projet. Cet article a pour but de trouver le générateur de site statique parfait pour toute occasion ; quelque chose qui nous permet d'utiliser des modèles sans JS comme Markdown pour commencer, et d'apporter des « îlots » d'interactivité basée sur les composants selon les besoins.
Je distille une année d'apprentissages dans un seul article ici. Non seulement nous allons parler de code (alias duct-taping 11ty et Vite ensemble), mais nous allons également explorer pourquoi cette approche est si universelle pour les problèmes Jamstackian. Nous aborderons :
- Deux approches de la génération de sites statiques, et pourquoi nous devrions combler l'écart ;
- Où les langages de modélisation comme Pug et Nunjucks s'avèrent toujours utiles ;
- Quand les frameworks de composants comme React ou Svelte devraient venir en jeu ;
- Comment le nouveau monde de rechargement à chaud de Vite nous aide à apporter de l'interactivité JS à notre HTML avec presque aucune configuration ;
- Comment cela complète la cascade de données de 11ty, en apportant des données CMS à n'importe quel framework de composant ou modèle HTML que vous pourrait vouloir.
Alors, sans plus tarder, voici mon histoire de terribles scripts de construction, de percées dans le bundle et de spaghetti-code-duct-tape qui m'ont (finalement) donné le SSG que j'ai toujours voulu: un sandwich 11ty, Vite and Jam appelé Slinkity !
Une grande division dans la génération de sites statiques
Avant de plonger, je veux discuter de ce que j'appellerai deux « camps » dans la génération de sites statiques.
Dans le premier camp. , nous avons le générateur de site statique "simple". Ces outils n'apportent pas d'ensembles JavaScript, d'applications d'une seule page et d'autres mots à la mode auxquels nous nous attendons. Ils ne font que maîtriser les principes fondamentaux de Jamstack : extrayez les données de n'importe quel blob JSON du CMS que vous préférez et glissez ces données dans des modèles HTML simples + CSS. Des outils tels que Jekyll, Hugo et 11ty dominent ce camp, vous permettant de transformer un répertoire de fichiers markdown et liquid en un site Web entièrement fonctionnel. Principaux avantages :
- Courbe d'apprentissage peu profonde
Si vous connaissez le HTML, vous êtes prêt à partir ! - Délai de création rapide
Nous ne traitons rien de complexe, donc chaque itinéraire se construit en un clin d'œil. - Temps instantané d'interaction
Il n'y a pas (ou très peu) de JavaScript à analyser sur le client.
Maintenant dans le deuxième camp, nous avons le « dynamique » générateur de site statique. Ceux-ci introduisent des frameworks de composants tels que React, Vue et Svelte pour apporter de l'interactivité à votre Jamstack. Ceux-ci remplissent la même promesse fondamentale de combiner les données CMS avec les itinéraires de votre site au moment de la construction. Principaux avantages :
- Construit pour l'interactivité
Besoin d'un carrousel d'images animées ? Formulaire en plusieurs étapes ? Ajoutez simplement une pépite de HTML, CSS et JS. Par exemple, le panier sur votre site de commerce électronique.
Les deux approches présentent des avantages distincts. Mais que se passe-t-il si vous choisissez un SSG du premier camp comme Jekyll, pour réaliser seulement six mois après le début de votre projet que vous avez besoin d'une certaine interactivité entre les composants ? Ou vous choisissez quelque chose comme NextJS pour ces composants puissants, seulement pour lutter avec la courbe d'apprentissage de React, ou des Ko inutiles de JavaScript sur un article de blog statique ? autre à mon avis. Ils existent sur un spectre, favorisant constamment de nouveaux ensembles de fonctionnalités à mesure que les besoins d'un projet évoluent. Alors, comment trouver une solution qui nous permet de démarrer avec les outils simples du premier camp, et d'ajouter progressivement des fonctionnalités du second lorsque nous en avons besoin ?
Eh bien, passons en revue mon parcours d'apprentissage pour un peu.
Remarque : Si vous êtes déjà convaincu par les modèles statiques avec 11ty pour créer vos sites statiques, n'hésitez pas à passer à la procédure pas à pas de code juteux. 😉
Passer des composants aux modèles et aux API Web[19659012] En janvier 2020, j'ai entrepris de faire ce que presque tous les développeurs Web font chaque année : reconstruire mon site personnel. Mais cette fois allait être différent. Je me suis lancé le défi de créer un site les mains liées dans le dos, pas de frameworks ni de pipelines de construction autorisés !
Ce n'était pas une tâche simple en tant que passionné de React. Mais la tête haute, je me suis mis à construire mon propre pipeline de construction à partir de zéro absolu. Il y a beaucoup de code mal écrit que je pourrais partager à partir de la v1 de mon site personnel… mais je vous laisse cliquer sur ce README si vous êtes si courageux. 😉 Au lieu de cela, je veux me concentrer sur les plats à emporter de niveau supérieur que j'ai appris en me privant de mes plaisirs coupables JS.
Les modèles vont beaucoup plus loin que vous ne le pensez
Il y a quelques besoins liés au site statique que j'ai adoré utiliser des frameworks basés sur des composants :
- Nous voulons décomposer mon site en composants d'interface utilisateur réutilisables qui peuvent accepter des objets JS comme paramètres (alias « accessoires ») .
- Nous devons récupérer des informations au moment de la construction pour entrer dans un site de production.
- Nous devons générer un tas de routes URL à partir d'un répertoire de fichiers ou un gros objet de contenu JSON.
Liste tirée de cet article sur mon blog personnel.
Mais vous avez peut-être remarqué… aucun de ces vraiment besoin JavaScript côté client. Les frameworks de composants tels que React sont principalement conçus pour gérer les problèmes de gestion de l'état, comme l'application Web Facebook inspirant React en premier lieu. Si vous ne faites que décomposer votre site en composants de petite taille ou en éléments de système de conception, des modèles tels que Pug fonctionnent également très bien !
Prenez cette barre de navigation par exemple. Dans Pug, nous pouvons définir un « mixin » qui reçoit des données en tant qu'accessoires :
// nav-mixins.pug
mixin NavBar(liens)
// version de pug d'une boucle for
chaque lien dans les liens
a(href=link.href) link.text
Ensuite, nous pouvons appliquer ce mixin n'importe où sur notre site.
// index.pug
// un peu comme une "importation" ESM
inclure nav-mixins.pug
html
corps
+NavBar(navLinksPassedByJS)
principale
h1 Bienvenue sur mon terrain de jeu carlin 🐶
Si nous « rendons » ce fichier avec quelques données, nous obtiendrons un magnifique index.html
à servir à nos utilisateurs.
const html = pug .render('/index.pug', { navLinksPassedByJS : [
{ href: '/', text: 'Home' },
{ href: '/adopt', text: 'Adopt a Pug' }
] })
// utiliser les assistants du système de fichiers NodeJS pour écrire un fichier dans notre build
wait writeFile('build/index.html', html)
Bien sûr, cela ne donne pas de subtilités comme le CSS étendu pour vos mixins ou le JavaScript avec état où vous le souhaitez. Mais il a des avantages très puissants par rapport à quelque chose comme React :
- Nous n'avons pas besoin de bundlers sophistiqués que nous ne comprenons pas.
Nous venons d'écrire quepug.render
appelle à la main, et nous avons déjà la première route d'un site prêt à être déployé. - Nous n'envoyons aucun JavaScript à l'utilisateur final.
Utiliser React signifie souvent envoyer un gros runtime pour que les navigateurs des gens s'exécutent. . En appelant une fonction commepug.render
au moment de la construction, nous gardons tout le JS de notre côté tout en envoyant un fichier.html
propre à la fin.
C'est pourquoi je pensez que les modèles sont une excellente "base" pour les sites statiques. Pourtant, être capable d'atteindre des frameworks de composants où nous en profitons vraiment serait bien. Plus à ce sujet plus tard. 🙃
Vous n'avez pas besoin d'un framework pour créer des applications à page unique
Pendant que j'y étais, je voulais aussi des transitions de page sexy sur mon site. Mais comment pouvons-nous réaliser quelque chose comme ça sans cadre?

Eh bien, nous ne pouvons pas faire cela si chaque page est son propre fichier .html
. L'ensemble du navigateur se rafraîchit lorsque nous passons d'un fichier HTML à l'autre, nous ne pouvons donc pas avoir ce bel effet de fondu enchaîné (puisque nous montrerions brièvement les deux pages l'une sur l'autre).
Nous avons besoin d'un moyen pour « récupérer » le HTML et le CSS partout où nous naviguons et l'animer à l'aide de JavaScript. Cela ressemble à un travail pour les applications d'une seule page !
J'ai utilisé un simple mélange d'API de navigateur pour cela :
- Interceptez tous vos clics sur les liens à l'aide d'un écouteur d'événements.
- fetch API : Récupérez toutes les ressources pour la page de votre choix. à visiter et saisir le bit que je veux animer : le contenu en dehors de la barre de navigation (que je veux rester immobile pendant l'animation).
- API d'animations web : Animez le nouveau contenu en tant qu'image clé.
- history API : Modifiez l'itinéraire affiché dans la barre d'URL de votre navigateur à l'aide de
window.history.pushState({}, « nouvelle route »)
. Sinon, il semble que vous n'ayez jamais quitté la page précédente !
Pour plus de clarté, voici une illustration visuelle de ce concept d'application à page unique à l'aide d'une simple recherche et remplacement :

Vous pouvez également visiter le code source de mon site personnel ![19659003] Bien sûr, une combinaison de React et al et de la bibliothèque d'animation de votre choix peut le faire. Mais pour un cas d'utilisation aussi simple qu'une transition en fondu… les API Web sont assez puissantes en elles-mêmes. Et si vous souhaitez des transitions de page plus robustes sur des modèles statiques tels que Pug ou HTML simple, des bibliothèques telles que Swup vous seront très utiles.
What 11ty Brought To The Table
Je me sentais plutôt bien avec mon petit SSG à ce stade. Bien sûr, il ne pouvait récupérer aucune donnée CMS au moment de la construction, et ne prenait pas en charge différentes mises en page par page ou par répertoire, et n'optimisait pas mes images et n'avait pas de versions incrémentielles.
D'accord, je pourrais besoin d'aide.
Compte tenu de tous mes apprentissages de la v1, je pensais avoir gagné mon droit d'abandonner la règle « pas de pipelines de construction tiers » et d'utiliser les outils existants. Il s'avère que 11ty a un trésor de fonctionnalités dont j'ai besoin !
Si vous avez essayé des SSG simples comme Jekyll ou Hugo, vous devriez avoir une assez bonne idée du fonctionnement de 11ty. Seule différence ? 11ty utilise JavaScript de bout en bout.
11ty prend en charge pratiquement toutes les bibliothèques de modèles, il était donc heureux de rendre toutes mes pages Pug sur les routes .html
. Son option de chaînage de mise en page m'a également aidé avec la configuration de mon application ennemie à page unique. J'avais juste besoin d'un seul script
pour toutes mes routes, et d'une mise en page « globale » pour importer ce script :
// _includes/base-layout.html
{{ contenu }}
// aléatoire-blog-post.pug
---
mise en page : mise en page de base
---
article
h2 Bienvenue sur mon blog
p Avez-vous entendu l'histoire de Dark Plagueis le Sage ? Oh, et la cascade de données
Donc, 11ty m'a aidé à nettoyer tout mon code spaghetti de la v1. Mais cela a apporté un autre élément important : une API propre pour charger des données dans mes mises en page. C'est le pain et le beurre de l'approche Jamstack. Au lieu de récupérer des données dans le navigateur avec une manipulation JavaScript + DOM, vous pouvez :
- Récupérer des données au moment de la construction à l'aide de Node. Cela peut être un appel à une API externe, une importation locale JSON ou YAML, ou même le contenu d'autres routes sur votre site (imaginez mettre à jour une table des matières chaque fois que de nouveaux les routes sont ajoutées 🙃).
- Insérez ces données dans vos routes. Rappelez-vous que la fonction
.render
que nous avons écrite précédemment :
const html = pug.render('/index.pug', { navLinksPassedByJS: [
{ href: '/', text: 'Home' },
{ href: '/adopt', text: 'Adopt a Pug' }
] })
…mais au lieu d'appeler pug.render
avec nos données à chaque fois, nous laissons 11ty faire cela en coulisse.
Bien sûr, je n'avais pas beaucoup de données pour mon site personnel. Mais c'était génial de créer un fichier .yaml
pour tous mes projets personnels :
# _data/works.yaml
- titre : Bits of Good Page d'accueil
hachage : page d'accueil de la tourbière
liens:
-href : https://bitsoftow.org
texte : Explorez le site en direct
-href : https://github.com/GTBitsOfGood/bog-web
texte : Parcourir la base de code Svelt-ified
calendrier : mai 2019 - présent
Mots clés:
- JAMstack
- SvelteJS
- titre : Visualiseur audio Dolphin
...
Et accédez à ces données sur n'importe quel modèle :
// home.pug
.project-carrousel
chaque oeuvre en oeuvre
h3 #{titre}
p #{délai}
chaque balise dans les balises
...
Venant du monde du "rendu côté client" avec create-react-appce fut une assez grosse révélation. Plus besoin d'envoyer des clés API ou de gros blobs JSON au navigateur. 😁
J'ai également ajouté quelques goodies pour la récupération de JavaScript et des améliorations d'animation par rapport à la version 1 de mon site. Si vous êtes curieux, voici où se trouvait mon fichier README à ce stade.
J'étais heureux à ce stade mais quelque chose manquait
Je suis allé étonnamment loin en abandonnant les composants basés sur JS et en adoptant les modèles (avec des transitions de page animées pour démarrer). Mais je sais que cela ne satisfera pas mes besoins pour toujours. Vous vous souvenez de cette grande division avec laquelle je nous ai lancés ? Eh bien, il y a clairement toujours ce ravin entre ma configuration de construction (fermement dans le camp #1) et le havre de l'interactivité JS-ified (le Next, SvelteKit, et plus du camp #2). Supposons que je souhaite ajouter :
- un modal contextuel avec une bascule ouvrir/fermer,
- un système de conception basé sur des composants comme Material UIcomplet avec un style à portée,
- un complexe forme en plusieurs étapes, peut-être pilotée par une machine à états.
Si vous êtes un puriste de JS, vous avez probablement des réponses sans framework à tous ces cas d'utilisation. 😉 Mais il y a une raison pour laquelle JQuery n'est plus la norme ! Il y a quelque chose d'attrayant à créer des composants HTML discrets et faciles à lire, des styles délimités et des morceaux de variables d'état JavaScript. React, Vue, Svelte, etc. offrent tellement de subtilités pour le débogage et les tests que la manipulation directe du DOM ne peut pas tout à fait correspondre.
Voici donc ma question à un million de dollars : pouvons-nous utiliser des modèles HTML simples pour commencer, et progressivement ajouter des composants React / Vue / Svelte où nous les voulons ?
La réponse… est oui. Essayons-le.
11ty + Vite: A Match Made In Heaven ❤️
Voici le rêve que j'imagine ici. Partout où je veux insérer quelque chose d'interactif, je veux laisser un petit indicateur dans mon modèle pour "mettre le composant X React ici". Cela pourrait être la syntaxe de shortcode prise en charge par 11ty :
# Tutoriel de programmation super intéressant
Écrire des paragraphes a été amusant, mais ce n'est pas une façon d'apprendre. C'est l'heure d'un exemple de code interactif !
{% react './components/FancyLiveDemo.jsx' %}
Mais rappelez-vous, le 11ty monobloc évite (à dessein) : un moyen de regrouper tout votre JavaScript. Venant de la guilde OG du regroupement, votre cerveau passe probablement à la création de processus Webpack, Rollup ou Babel ici. Construisez un gros fichier de point d'entrée ole et sortez un beau code optimisé, n'est-ce pas ?
Eh bien, oui, mais cela peut devenir assez compliqué. Si nous utilisons des composants React, par exemple, nous aurons probablement besoin de chargeurs pour JSX, d'un processus Babel sophistiqué pour tout transformer, d'un interpréteur pour les importations de modules SASS et CSS, quelque chose pour aider au rechargement en direct , et ainsi de suite.
Si seulement il y avait un outil qui pouvait simplement voir nos fichiers .jsx
et savoir exactement quoi en faire.
Entrez : Vite
Vite a fait parler de lui ces derniers temps. Il est censé être l'outil tout-en-un pour créer à peu près n'importe quoi en JavaScript. Voici un exemple à essayer chez vous. Créons un répertoire vide quelque part sur notre machine et installons quelques dépendances :
npm init -y # Créer un nouveau package.json avec les valeurs par défaut définies
npm i vite react react-dom # Grab Vite + quelques dépendances pour utiliser React
Maintenant, nous pouvons créer un fichier index.html
pour servir de "point d'entrée" à notre application. Nous allons rester assez simple :
Document
Bonjour Vite ! (attendez qu'il se prononce "veet" ou "vight"...)
Le seul élément intéressant est que div id="root"
au milieu. Ce sera la racine de notre composant React dans un instant !
Si vous le souhaitez, vous pouvez lancer le serveur Vite pour voir notre fichier HTML brut dans votre navigateur. Exécutez simplement vite
(ou npx vite
si la commande n'a pas été configurée dans votre terminal), et vous verrez cette sortie utile :
vite vX.XX dev server courir à :
> Local : http://localhost:3000/
> Réseau : utilisez `--host` pour exposer
prêt dans Xms.
Tout comme Browsersync ou d'autres serveurs de développement populaires, le nom de chaque fichier .html
correspond à une route sur notre serveur. Donc, si nous renommions index.html
en about.html
nous visiterions http://localhost:3000/about/
(oui, vous aurez besoin une barre oblique finale !)
Faisons maintenant quelque chose d'intéressant. Parallèlement à ce fichier index.html
ajoutez un composant React de base d'une sorte. Nous utiliserons ici useState
de React pour démontrer l'interactivité :
// TimesWeMispronouncedVite.jsx
importer React à partir de 'react'
exporter la fonction par défaut TimesWeMispronouncedVite() {
const [count, setCount] = React.useState(0)
revenir (
J'ai mal dit Vite {count} fois aujourd'hui
)
}
Maintenant, chargeons ce composant sur notre page. C'est tout ce que nous avons à ajouter à notre index.html
:
...
Bonjour Vite ! (attendez qu'il se prononce "veet" ou "vight"...)