paint-brush
Créer un plugin personnalisé pour Vite : le guide le plus simplepar@gmakarov
1,012 lectures
1,012 lectures

Créer un plugin personnalisé pour Vite : le guide le plus simple

par German Makarov9m2024/01/21
Read on Terminal Reader

Trop long; Pour lire

Pour le serveur de développement, il utilise esbuild avec les modules ES natifs, qui sont pris en charge par les navigateurs modernes, et nous n'avons pas besoin de regrouper le code dans un seul fichier, et cela nous donne un HRM (Hot Module Remplacement) rapide. Pour le bundle, il utilise un rollup.js car il est flexible et dispose d'un vaste écosystème ; il permet la création de lots de production hautement optimisés avec différents formats de sortie. L'interface du plugin Vite est basée sur celle de Rollup mais avec des options et des crochets supplémentaires pour travailler avec le serveur de développement.
featured image - Créer un plugin personnalisé pour Vite : le guide le plus simple
German Makarov HackerNoon profile picture
0-item

Vite devient de plus en plus populaire parmi les développeurs, mais comme la communauté n'est pas aussi grande (comme dans Webpack ), vous devrez peut-être créer votre propre plugin personnalisé pour résoudre vos problèmes. Dans cet article, nous verrons comment créer un plugin pour Vite et je décomposerai mon propre plugin.

Comment fonctionnent les plugins dans Vite

Pour créer un plugin, il est important de savoir que Vite utilise des systèmes de build différents pour le serveur de développement (commande vite ) et le bundle (commande vite build ).


Pour le serveur de développement, il utilise esbuild avec les modules ES natifs, qui sont pris en charge par les navigateurs modernes, et nous n'avons pas besoin de regrouper le code dans un seul fichier, et cela nous donne un HRM (Hot Module Remplacement) rapide.


Pour le bundle, il utilise un rollup.js car il est flexible et dispose d'un vaste écosystème ; il permet la création de lots de production hautement optimisés avec différents formats de sortie.


L'interface du plugin de Vite est basée sur celle de Rollup mais avec des options et des crochets supplémentaires pour travailler avec le serveur de développement.

Création d'un plugin de base

Lorsque vous créez un plugin, vous pouvez l'intégrer dans votre vite.config.js . Il n'est pas nécessaire de créer un nouveau package pour cela. Une fois que vous voyez qu'un plugin a été utile dans vos projets, pensez à le partager avec la communauté et à contribuer à l'écosystème Vite.


De plus, étant donné que rollup.js dispose d'une communauté et d'un écosystème plus importants, vous pourriez envisager de créer un plugin pour rollup.js, et cela fonctionnera tout aussi bien dans Vite. Ainsi, si la fonctionnalité de votre plugin ne fonctionne que pour le bundle, vous pouvez utiliser le plugin rollup.js au lieu de Vite, et les utilisateurs peuvent utiliser votre plugin rollup dans leurs projets Vite sans aucun problème.


Si vous créez un plugin pour rollup, vous couvrirez davantage d'utilisateurs qui utilisent uniquement rollup.js. Si votre plugin affectera le serveur de développement, alors vous optez pour le plugin Vite.


Commençons par créer le plugin directement dans vite.config.ts :


 // vite.config.ts import { defineConfig, Plugin } from 'vite'; function myPlugin(): Plugin { return { name: 'my-plugin', configResolved(config) { console.log(config); }, }; } export default defineConfig({ plugins: [ myPlugin(), ], });


Dans cet exemple, j'ai créé un plugin appelé myPlugin qui imprime la configuration Vite dès qu'elle est résolue dans la console dans les deux étapes : serveur de développement et bundle. Si je souhaite imprimer la configuration uniquement en mode serveur de développement, je dois alors ajouter apply: 'serve' et apply: 'build' pour le bundle.


 // vite.config.ts import { defineConfig, Plugin } from 'vite'; function myPlugin(): Plugin { return { name: 'my-plugin', apply: 'serve', configResolved(config) { console.log(config); }, }; } export default defineConfig({ plugins: [ myPlugin(), ], });


De plus, je peux renvoyer une gamme de plugins ; c'est utile pour séparer les fonctionnalités du serveur de développement et du bundle :


 // vite.config.ts import { defineConfig, Plugin } from 'vite'; function myPlugin(): Plugin[] { return [ { name: 'my-plugin:serve', apply: 'serve', configResolved(config) { console.log('dev server:', config); }, }, { name: 'my-plugin:build', apply: 'build', configResolved(config) { console.log('bundle:', config); }, }, ]; } export default defineConfig({ plugins: [ myPlugin(), ], });


Et c'est à peu près tout; vous pouvez facilement ajouter de petits plugins à la configuration Vite. Et si un plugin devient trop gros, je préfère le déplacer vers un autre fichier ou même créer un package.


Si vous avez besoin de quelque chose de plus complexe, il existe de nombreux hooks utiles que vous pouvez explorer dans la documentation de Vite. Mais à titre d'exemple, décomposons mon propre plugin ci-dessous.

Décomposer un vrai plugin

J'ai donc un plugin pour créer des sprites SVG basés sur des fichiers d'icônes - vite-plugin-svg-spritemap .

Le but est de récupérer toutes les icônes .svg dans le dossier src/icons et de collecter leur contenu dans un seul fichier .svg appelé sprite SVG. Commençons par l'étape du bundle :


 import { Plugin, ResolvedConfig } from 'vite'; import path from 'path'; import fs from 'fs-extra'; function myPlugin(): Plugin { let config: ResolvedConfig; return { name: 'my-plugin:build', apply: 'build', async configResolved(_config) { config = _config; }, writeBundle() { const sprite = getSpriteContent({ pattern: 'src/icons/*.svg' }); const filePath = path.resolve(config.root, config.build.outDir, 'sprite.svg'); fs.ensureFileSync(filePath); fs.writeFileSync(filePath, sprite); }, }; }


  1. Hook configResolved nous permet d'obtenir la configuration lorsqu'il est résolu de l'utiliser dans les prochains hooks ;


  2. Le hook writeBundle est appelé une fois le processus de regroupement terminé, et ici, je vais créer le fichier sprite.svg ;


  3. La fonction getSpriteContent renvoie une chaîne de sprites SVG préparés basés sur le modèle src/icons/*.svg . Je n'irai pas plus loin avec celui-ci ; vous pouvez consulter mon autre article expliquant tout le processus de génération de sprite SVG ;


  4. Ensuite, je crée le chemin absolu vers le sprite.svg pour y insérer le contenu du sprite SVG avec path.resolve() , je m'assure que ce fichier existe (ou j'en crée un) avec fs.ensureFileSync ., et j'y écris le contenu du sprite SVG. .


Passons maintenant à la partie la plus intéressante : l’étape du serveur de développement. Je ne peux pas utiliser writeBundle ici, et je ne peux pas héberger de fichiers lorsque le serveur de développement est en cours d'exécution, nous devons donc utiliser un middleware de serveur pour intercepter la requête adressée à sprite.svg .


 import { Plugin, ResolvedConfig } from 'vite'; function myPlugin(): Plugin { let config: ResolvedConfig; return { name: `my-plugin:serve`, apply: 'serve', async configResolved(_config) { config = _config; }, configureServer(server) { // (1) return () => { server.middlewares.use(async (req, res, next) => { // (2) if (req.url !== '/sprite.svg') { return next(); // (3) } const sprite = getSpriteContent({ pattern, prefix, svgo, currentColor }); res.writeHead(200, { // (4) 'Content-Type': 'image/svg+xml, charset=utf-8', 'Cache-Control': 'no-cache', }); res.end(sprite); }); }; }, }; }


  1. configureServer est un hook pour configurer le serveur de développement. Il se déclenche avant l'installation du middleware interne de Vite ; dans mon cas, je dois ajouter un middleware personnalisé après le middleware interne, donc je renvoie une fonction ;


  2. Pour ajouter un middleware personnalisé afin de détecter chaque requête adressée au serveur de développement, j'utilise server.middlewares.use() . J'en ai besoin pour détecter les requêtes avec l'URL [localhost:3000/sprite.svg](http://localhost:3000/sprite.svg) , afin de pouvoir émuler le comportement des fichiers ;


  3. Si l'URL de la requête n'est pas /sprite.svg - passez au middleware suivant (c'est-à-dire, passez le contrôle au gestionnaire suivant dans la chaîne) ;


  4. Pour préparer le contenu du fichier, je mets le résultat de getSpriteContent dans le sprite variable et l'envoie en réponse avec les en-têtes configurés (type de contenu et statut HTTP 200).


En conséquence, j'ai simulé le comportement des fichiers.


Mais si des fichiers dans src/icons sont modifiés, supprimés ou ajoutés, nous devons redémarrer le serveur pour générer un nouveau contenu de sprite via getSpriteContent ; pour cela, j'utiliserai la bibliothèque de surveillance de fichiers - chokidar . Ajoutons les gestionnaires chokidar au code :


 import { Plugin, ResolvedConfig } from 'vite'; import chokidar from 'chokidar'; function myPlugin(): Plugin { let config: ResolvedConfig; let watcher: chokidar.FSWatcher; // Defined variable for chokidar instance. return { name: `my-plugin:serve`, apply: 'serve', async configResolved(_config) { config = _config; }, configureServer(server) { function reloadPage() { // Function that sends a signal to reload the server. server.ws.send({ type: 'full-reload', path: '*' }); } watcher = chokidar .watch('src/icons/*.svg', { // Watch src/icons/*.svg cwd: config.root, // Define project root path ignoreInitial: true, // Don't trigger chokidar on instantiation. }) .on('add', reloadPage) // Add listeners to add, modify, delete. .on('change', reloadPage) .on('unlink', reloadPage); return () => { server.middlewares.use(async (req, res, next) => { if (req.url !== '/sprite.svg') { return next(); } const sprite = getSpriteContent({ pattern, prefix, svgo, currentColor }); res.writeHead(200, { 'Content-Type': 'image/svg+xml, charset=utf-8', 'Cache-Control': 'no-cache', }); res.end(sprite); }); }; }, }; }


Comme vous pouvez le constater, l’API de création de plugin n’est pas vraiment compliquée. Il vous suffit de trouver des hooks de Vite ou Rollup qui correspondront à vos tâches. Dans mon exemple, j'utilise writeBundle de Rollup.js (comme je l'ai dit, il est utilisé pour générer le bundle) et configureServer de Vite car Rollup.js ne prend pas en charge le serveur de développement natif.


Dans le cas du writeBundle c'était très simple, nous avons pris le contenu du sprite SVG et l'avons mis dans un fichier. Dans le cas du serveur de développement, je ne comprenais pas pourquoi je ne pouvais pas faire de même ; J'ai regardé les plugins d'autres auteurs, et ils font tous à peu près la même chose.


J'utilise donc configureServer et via l'argument server , j'ajoute un middleware qui déclenche chaque requête au serveur de développement en interceptant la requête sprite.svg .

Utiliser les crochets Vite

Comme je l'ai déjà mentionné, pour créer des plugins plus utiles, vous devez explorer les hooks. Ils sont expliqués en détail dans la documentation :

https://vitejs.dev/guide/api-plugin#universal-hooks

https://vitejs.dev/guide/api-plugin#vite-special-hooks

Comment nommer un plugin

En termes de dénomination, Vite a certaines conventions pour les plugins, vous feriez donc mieux de les vérifier avant de terminer. Voici quelques points clés :


  • Les plugins Vite doivent avoir un nom unique avec un préfixe vite-plugin- ;


  • Incluez le mot-clé vite-plugin dans package.json ;


  • Incluez une section dans la documentation du plugin expliquant pourquoi il s'agit d'un plugin uniquement Vite (par exemple, il utilise des hooks de plugin spécifiques à Vite) ;


  • Si votre plugin ne fonctionne que pour un framework spécifique, incluez son nom dans le préfixe ( vite-plugin-vue- , vite-plugin-react- , vite-plugin-svelte- ).

Comment publier et partager votre plugin

Si vous décidez de publier votre plugin en NPM, ce que je recommande car le partage des connaissances et des expertises est un principe fondamental de la communauté informatique, favorisant la croissance collective. Pour savoir comment publier et maintenir votre package, consultez mon guide → Le moyen le plus simple de créer un package NPM .


Je recommande également fortement de soumettre votre plugin à la liste de la communauté vite - Awesome-vite . Beaucoup de personnes y recherchent les plugins les plus adaptés, et ce serait une belle opportunité de contribuer à l’écosystème Vite ! Le processus de soumission de votre plugin est simple : assurez-vous simplement de respecter les conditions et de créer une pull request. Vous pouvez trouver la liste des termes ici .


Dans l'ensemble, il doit être spécifique à Vite (et non au rollup), open source et disposer d'une bonne documentation. Bonne chance avec vos plugins !