Créer un Playground et un Storybook pour les Composants
Nous avons des composants et des tests, mais jusqu'à présent, nous n'avons pas pu les voir en action. Il est temps de créer un playground pour deux raisons principales :
- Tests : Nous devons tester nos composants dans un environnement réel pour nous assurer qu'ils fonctionnent comme prévu. Écrire une page avec tous les composants, leurs props et slots aide à créer la meilleure API et à l'implémenter efficacement. Cette approche minimise les refactorisations fréquentes en fournissant une vue d'ensemble des composants.
- Visualisation : La visualisation des composants est essentielle. Bien que Tailwind CSS simplifie le style, il est impossible de bien saisir un composant par le code, en particulier les composants complexes avec de nombreuses variantes ou slots. Un playground nous permet de voir les composants en action et de les tester dans divers scénarios.
Configuration du Playground
Tout d'abord, créez un nouveau dossier nommé playground
à la racine de votre projet.
mkdir playground
Ensuite, créez un nouveau projet Vite dans ce dossier, qui dépendra de notre bibliothèque de composants. Être dans un monorepo simplifie ce processus.
cd playground && pnpm create vite --template vue-ts
Nommez ce projet vue
.
Avant d’installer les dépendances, mettez à jour le pnpm-workspace.yaml
pour inclure le package playground/vue
. Cela permet au playground d'accéder à la bibliothèque de composants.
packages:
- 'packages/*'
- 'playground/*'
Installez les dépendances du playground :
pnpm install
Dans ce playground Vue.js, supprimez les fichiers, dossiers et contenus inutiles :
rm -rf .vscode .public src/{assets,components}
echo "<template></template>" > src/App.vue
echo "" > src/style.css
Supprimez le dossier .vscode
, le dossier public
, les dossiers assets
et components
dans src
, ainsi que le contenu de App.vue
et style.css
.
Maintenant, installez la bibliothèque de composants dans le playground :
pnpm add ../../packages/huchet-vue
Cette commande installe la bibliothèque de composants en créant un lien symbolique vers celle-ci dans node_modules
. Ainsi, toute importation effectuée dans le playground résout la bibliothèque de composants dans le monorepo, permettant des modifications en temps réel pendant le développement.
Démarrez le script de surveillance dans le dossier du package huchet-vue
et le script de développement dans le dossier playground/vue
. Tout changement dans la bibliothèque de composants se reflétera dans le playground.
Utilisation du Playground
Avec la bibliothèque de composants installée dans le playground, vous pouvez commencer à l'utiliser.
Dans le fichier src/App.vue
, importez le composant Button
et utilisez-le :
<script lang="ts" setup>
import { Button } from '@barbapapazes/huchet-vue'
</script>
<template>
<div class="flex gap-6 p-6">
<Button label="Hello World" />
<Button label="Hello World" variant="outline" />
</div>
</template>
Pour voir le résultat, démarrez Vite dans le playground :
pnpm dev
Ensuite, démarrez Vite dans la bibliothèque de composants :
pnpm watch
Important
Plus votre bibliothèque contient de composants, plus il faudra de temps pour refléter les changements dans le playground. Si cela commence à ralentir, envisagez d'importer directement le composant depuis la bibliothèque avec un chemin relatif ou d'utiliser un storybook comme Histoire, que nous allons aborder ensuite.
Dans votre navigateur, vous devriez voir deux boutons, non stylisés.
Styliser le Playground
Nos composants sont non stylisés. Pour réduire la taille du bundle et permettre la génération côté utilisateur, nous ne fournissons pas de CSS avec la bibliothèque de composants.
Note
Nous pourrions expédier une configuration Tailwind CSS avec la bibliothèque de composants pour garantir que les composants sont correctement stylés dans le playground.
Nous allons utiliser Tailwind CSS 4, même s'il n'est pas encore sorti, car il est accompagné d'un plugin Vite qui simplifie son utilisation et aucun autre changement cassant n'est attendue.
pnpm i -D tailwindcss@next @tailwindcss/vite@next
Ensuite, enregistrez le plugin Tailwind CSS dans le fichier vite.config.ts
:
import Tailwindcss from '@tailwindcss/vite'
import Vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
Vue(),
Tailwindcss(),
],
})
Dans le src/style.css
, importez les styles Tailwind CSS :
@import "tailwindcss";
Automatiquement, les boutons sont stylés comme prévu.
Le Storybook Histoire
Parfois, un playground ne suffit pas. Vous avez besoin de documenter vos composants, de les visualiser dans divers scénarios et de les isoler pour vous assurer que les problèmes proviennent du composant et non de l'intégration. C'est ici qu'un storybook entre en jeu.
Nous allons utiliser Histoire, un outil similaire à Storybook qui est léger, basé sur Vite et optimisé pour Vue.js.
Configuration de Histoire
La configuration de Histoire est simple, surtout avec Tailwind CSS 4.
Tout d'abord, créez un nouveau dossier depuis la racine du projet :
mkdir .histoire && cd .histoire && echo '{\n"name": "huchet-vue-histoire",\n"private": true\n}' > package.json
Note
J'ai placé le dossier Histoire à la racine du projet au lieu du dossier packages
car c'est un outil de développement, et non un package npm publiable.
Ajoutez le dossier au workspace :
echo " - .histoire" >> ../pnpm-workspace.yaml
Installez Histoire et Tailwind CSS :
pnpm i -D histoire @histoire/plugin-vue @vitejs/plugin-vue vue tailwindcss@next @tailwindcss/vite@next
Note
Nous installons maintenant Tailwind CSS car nous en aurons besoin, comme nous l'avons vu dans le playground.
Histoire utilise un fichier de configuration nommé histoire.config.ts
, que nous allons créer dans le dossier .histoire
:
touch histoire.config.ts
La configuration comprend plusieurs clés :
plugins
: Plugins pour Histoire, comme le plugin Vue Histoire.storyMatch
: Fichiers à correspondre pour créer des histoires, comme les fichiers*.story.vue
.setupFile
: Fichier de configuration à utiliser avec Histoire, où nous allons créer unsetup.ts
.theme
: Options de personnalisation comme le titre, le logo, le favicon pour l'interface Histoire.vite
: Configuration Vite utilisant les plugins Vue et Tailwind CSS.
import { resolve } from 'node:path'
import { HstVue } from '@histoire/plugin-vue'
import Tailwind from '@tailwindcss/vite'
import Vue from '@vitejs/plugin-vue'
import { defineConfig } from 'histoire'
export default defineConfig({
plugins: [HstVue()],
storyMatch: [
resolve(__dirname, '../packages/huchet-vue/src/**/*.story.vue'),
],
setupFile: resolve(__dirname, 'setup.ts'),
theme: {
title: 'Huchet Vue',
},
vite: {
plugins: [
Vue(),
Tailwind(),
],
server: {
fs: {
allow: ['..'],
},
},
},
})
Puisque les histoires se trouvent dans la bibliothèque de composants, nous devons explicitement indiquer à Histoire de les chercher dans le dossier packages/huchet-vue/src
à l'aide de la clé storyMatch
. Pendant ce temps, nous permettons au serveur Histoire d'accéder au dossier parent via la clé server.fs.allow
, empêchant ainsi les problèmes d'accessibilité aux fichiers.
Pour implémenter Tailwind CSS dans Histoire, importez le CSS dans le fichier setup.ts
, de la même manière que dans le playground :
touch setup.ts style.css
echo "import './style.css';" > setup.ts
echo "@import 'tailwindcss';" > style.css
Note
Le fichier setup.ts
est exécuté au démarrage de Histoire et est un endroit idéal pour la personnalisation ou les styles globaux.
Pour commencer avec Histoire, ajoutez trois scripts au package.json
:
{
"scripts": {
"dev": "histoire dev",
"build": "histoire build",
"serve": "histoire serve"
}
}
Maintenant, nous pouvons démarrer Histoire :
pnpm dev
Création d'une Histoire
En revenant à packages/huchet-vue
, nous pouvons créer notre premier fichier d'histoire, Button/Button.story.vue
:
touch src/Button/Button.story.vue
Histoire propose des composants prédéfinis pour créer une histoire avec des variantes.
Story
: Le composant principal pour créer une histoire.Variant
: Un composant pour créer une variante d'un composant au sein de l'histoire.
Dans notre scénario, nous créons une histoire dans Button.story.vue
avec deux variantes : solid
et outline
.
<script lang="ts" setup>
import { logEvent } from 'histoire/client'
import Button from './Button.vue'
</script>
<template>
<Story>
<Variant title="Solid">
<Button variant="solid" label="Hello World" @click="logEvent('Click', $event)" />
</Variant>
<Variant title="Outline">
<Button variant="outline" label="Hello World" @click="logEvent('Click', $event)" />
</Variant>
</Story>
</template>
Note
La fonction logEvent
enregistre les événements dans l'interface, aidant les développeurs à comprendre la sortie du composant.
Et cela fonctionne !
Cependant, un problème majeur persiste : les composants Story
et Variant
ne sont pas reconnus par notre éditeur.
Ajout des Types Histoire
Heureusement, nous pouvons résoudre ce problème facilement car Histoire fournit les outils nécessaires.
Histoire introduit un nouveau contexte TypeScript dans notre projet, nous devons donc créer un nouveau fichier TSConfig dans le dossier packages/huchet-vue
:
touch tsconfig.story.json
Ce fichier étend tsconfig.app.json
mais capture uniquement les fichiers story.vue
et un nouveau fichier histoire.d.ts
:
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"moduleResolution": "node"
},
"include": [
"histoire.d.ts",
"src/**/*.story.vue"
],
"exclude": []
}
Note
L'option moduleResolution
est essentielle pour une résolution correcte des modules. Le package @vue/tsconfig
utilise Bundler
, mais nous avons besoin de Node
pour notre cas d'utilisation. Assurez-vous que "exclude": []
écrase l'option exclude
dans tsconfig.app.json
.
Créez le fichier histoire.d.ts
:
touch histoire.d.ts
Référencez les types d'Histoire dans ce fichier :
/// <reference types="@histoire/plugin-vue/components" />
Enregistrez le nouveau TSConfig dans le tsconfig.json
:
{
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.story.json"
}
]
}
Mettez à jour tsconfig.app.json
avec une option exclude
pour éviter la capture de TSConfig qui se chevauche :
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": [
"src/**/*.ts",
"src/**/*.vue"
],
"exclude": [
"src/**/*.story.vue"
]
}
Note
Les captures TSConfig qui se chevauchent peuvent entraîner des comportements inattendus et de nombreux problèmes. Assurez-vous de définir des limites claires entre les TSConfigs pour éviter des conflits.
Dans le prochain article, nous améliorerons l'intégration avec l'écosystème Vue.js en créant un résolveur pour Unplugin Vue Component et un module Nuxt.
Merci de me lire ! Je m'appelle Estéban, et j'adore écrire sur le développement web.
Je code depuis plusieurs années maintenant, et j'apprends encore de nouvelles choses chaque jour. J'aime partager mes connaissances avec les autres, car j'aurais aimé avoir accès à des ressources aussi claires et complètes lorsque j'ai commencé à apprendre la programmation.
Si vous avez des questions ou souhaitez discuter, n'hésitez pas à commenter ci-dessous ou à me contacter sur Bluesky, X, et LinkedIn.
J'espère que vous avez apprécié cet article et appris quelque chose de nouveau. N'hésitez pas à le partager avec vos amis ou sur les réseaux sociaux, et laissez un commentaire ou une réaction ci-dessous—cela me ferait très plaisir ! Si vous souhaitez soutenir mon travail, vous pouvez me sponsoriser sur GitHub !