Communitygithub.com

vite-patterns

Modèles et bonnes pratiques pour Vite : configuration, plugins, HMR, variables d'environnement, proxy, SSR, mode bibliothèque et optimisation des builds.

Qu'est-ce que vite-patterns ?

Cette compétence fournit un guide complet et détaillé des bonnes pratiques pour les projets utilisant Vite 8+ (et versions antérieures). Elle couvre l'ensemble du cycle de vie d'un projet Vite, depuis la configuration initiale de `vite.config.ts` jusqu'à l'optimisation des builds de production, en passant par la gestion des variables d'environnement, la configuration du proxy de serveur de développement, le mode bibliothèque pour la publication de packages npm, et le pré-bundling des dépendances. Elle est utile à tout développeur travaillant avec Vite, que ce soit pour des applications React, Vue, ou d'autres frameworks, et fournit des conseils pour éviter les pièges courants comme les fuites de secrets via les variables d'environnement ou les différences de comportement entre les modes développement et production. La compétence explique le fonctionnement interne de Vite (mode développement ESM natif, build avec Rolldown/Rollup) et propose des exemples de code concrets pour la configuration, les plugins personnalisés, l'API HMR manuelle, l'optimisation des performances et le débogage.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/vite-patterns

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Modèles Vite

Modèles d'outil de build et de serveur de développement pour les projets Vite 8+. Couvre la configuration, les variables d'environnement, la configuration du proxy, le mode bibliothèque, le pré-bundling des dépendances et les pièges de production courants.

Quand l'utiliser

  • Configurer vite.config.ts ou vite.config.js
  • Mettre en place des variables d'environnement ou des fichiers .env
  • Configurer le proxy du serveur de développement pour des backends API
  • Optimiser la sortie du build (chunks, minification, assets)
  • Publier des bibliothèques avec build.lib
  • Résoudre les problèmes de pré-bundling des dépendances ou d'interopérabilité CJS/ESM
  • Déboguer les erreurs HMR, du serveur de développement ou de build
  • Choisir ou ordonner les plugins Vite

Comment ça fonctionne

  • Mode développement sert les fichiers sources en tant qu'ESM natif — pas de bundling. Les transformations sont effectuées à la demande pour chaque requête de module, ce qui explique pourquoi les démarrages à froid sont rapides et le HMR précis.
  • Mode build utilise Rolldown (v7+) ou Rollup (v5-v6) pour empaqueter l'application pour la production avec tree-shaking, code-splitting et minification basée sur Oxc.
  • Pré-bundling des dépendances convertit les dépendances CJS/UMD en ESM une fois via esbuild et met en cache le résultat sous node_modules/.vite, ce qui évite de refaire le travail lors des démarrages suivants.
  • Les plugins partagent une interface unifiée entre le développement et le build — le même objet plugin fonctionne à la fois pour les transformations à la demande du serveur de développement et pour la pipeline de production.
  • Les variables d'environnement sont intégrées statiquement au moment du build. Les variables préfixées par VITE_ deviennent des constantes publiques dans le bundle ; tout ce qui n'est pas préfixé est invisible pour le code client.

Exemples

Structure de configuration

Configuration de base

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: { '@': new URL('./src', import.meta.url).pathname },
  },
})

Configuration conditionnelle

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig(({ command, mode }) => {
  const env = loadEnv(mode, process.cwd())   // Préfixe VITE_ uniquement (sûr)

  return {
    plugins: [react()],
    server: command === 'serve' ? { port: 3000 } : undefined,
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  }
})

Options de configuration clés

CléDéfautDescription
root'.'Racine du projet (où se trouve index.html)
base'/'Chemin de base public pour les assets déployés
envPrefix'VITE_'Préfixe pour les variables d'environnement exposées au client
build.outDir'dist'Répertoire de sortie
build.minify'oxc'Minificateur ('oxc', 'terser', ou false)
build.sourcemapfalsetrue, 'inline', ou 'hidden'

Plugins

Plugins essentiels

La plupart des besoins en plugins sont couverts par une poignée de packages bien entretenus. Utilisez-les avant d'écrire les vôtres.

PluginObjectifQuand l'utiliser
@vitejs/plugin-react-swcReact HMR + Fast Refresh via SWCPar défaut pour les applications React (plus rapide que la variante Babel)
@vitejs/plugin-reactReact HMR + Fast Refresh via BabelSeulement si vous avez besoin de plugins Babel (emotion, décorateurs MobX)
@vitejs/plugin-vueSupport Vue 3 SFCApplications Vue
vite-plugin-checkerExécute tsc + ESLint dans un thread worker avec superposition HMRToute application TypeScript — Vite NE vérifie PAS les types pendant vite build
vite-tsconfig-pathsHonore les alias paths de tsconfig.jsonChaque fois que vous avez déjà des alias dans tsconfig.json
vite-plugin-dtsÉmet des fichiers .d.ts en mode bibliothèquePublication de bibliothèques TypeScript
vite-plugin-svgrImporte les SVG en tant que composants ReactApplications React utilisant des SVG comme composants
rollup-plugin-visualizerRapport de treemap/sunburst du bundleAudits périodiques de la taille du bundle (utiliser enforce: 'post')
vite-plugin-pwaPWA + Workbox sans configurationApplications fonctionnant hors ligne

Avertissement important : vite build transpile mais NE vérifie PAS les types. Les erreurs de type sont expédiées silencieusement en production à moins d'ajouter vite-plugin-checker ou d'exécuter tsc --noEmit dans le CI.

Création de plugins personnalisés

La création est rare — la plupart des besoins sont couverts par des plugins existants. Lorsque vous en avez besoin, commencez en ligne dans vite.config.ts et extrayez-le uniquement s'il est réutilisé.

// vite.config.ts — plugin en ligne minimal
function myPlugin(): Plugin {
  return {
    name: 'my-plugin',                       // obligatoire, doit être unique
    enforce: 'pre',                           // 'pre' | 'post' (optionnel)
    apply: 'build',                           // 'build' | 'serve' (optionnel)
    transform(code, id) {
      if (!id.endsWith('.custom')) return
      return { code: transformCustom(code), map: null }
    },
  }
}

Hooks clés : transform (modifier la source), resolveId + load (modules virtuels), transformIndexHtml (injecter dans le HTML), configureServer (ajouter un middleware de développement), hotUpdate (HMR personnalisé — remplace handleHotUpdate obsolète dans v7+).

Modules virtuels utilisent la convention de préfixe \0 — resolveId retourne '\0virtual:my-id' pour que les autres plugins l'ignorent. Le code utilisateur importe 'virtual:my-id'.

Pour l'API complète des plugins, voir vite.dev/guide/api-plugin. Utilisez vite-plugin-inspect pendant le développement pour déboguer la pipeline de transformation.

API HMR

Les plugins de framework (@vitejs/plugin-react, @vitejs/plugin-vue, etc.) gèrent le HMR automatiquement. Utilisez import.meta.hot directement uniquement lors de la création de stores d'état personnalisés, d'outils de développement ou d'utilitaires agnostiques qui doivent persister l'état entre les mises à jour.

// src/store.ts — HMR manuel pour un module vanilla
if (import.meta.hot) {
  // Persister l'état entre les mises à jour (doit MUTER, ne JAMAIS réaffecter .data)
  import.meta.hot.data.count = import.meta.hot.data.count ?? 0

  // Nettoyer les effets de bord avant le remplacement du module
  import.meta.hot.dispose((data) => clearInterval(data.intervalId))

  // Accepter les propres mises à jour de ce module
  import.meta.hot.accept()
}

Tout le code import.meta.hot est supprimé par tree-shaking des builds de production — aucun retrait de garde nécessaire.

Variables d'environnement

Vite charge .env, .env.local, .env.[mode] et .[mode].local dans cet ordre (le dernier écrase le précédent) ; les fichiers *.local sont ignorés par git et destinés aux secrets locaux.

Accès côté client

Seules les variables préfixées par VITE_ sont exposées au code client :

import.meta.env.VITE_API_URL   // string
import.meta.env.MODE            // 'development' | 'production' | personnalisé
import.meta.env.BASE_URL        // valeur de config base
import.meta.env.DEV             // boolean
import.meta.env.PROD            // boolean
import.meta.env.SSR             // boolean

Utilisation des variables d'environnement dans la configuration

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd())          // Préfixe VITE_ uniquement (sûr)
  return {
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  }
})

Sécurité

Le préfixe VITE_ n'est PAS une barrière de sécurité

Toute variable préfixée par VITE_ est intégrée statiquement dans le bundle client au moment du build. La minification, l'encodage base64 et la désactivation des sourcemaps ne la cachent PAS. Un attaquant déterminé peut extraire n'importe quelle variable VITE_ du JavaScript livré.

Règle : Seules les valeurs publiques (URLs d'API, feature flags, clés publiques) vont dans les variables VITE_. Les secrets (jetons d'API, URLs de base de données, clés privées) DOIVENT résider côté serveur derrière une API ou une fonction serverless.

Le piège de loadEnv('')

// MAUVAIS : passer '' comme troisième argument charge TOUTES les variables d'environnement — y compris les secrets serveur —
// et les rend disponibles pour être intégrées dans le code client via `define`.
const env = loadEnv(mode, process.cwd(), '')

// BON : liste de préfixes explicite
const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_'])

Source Maps en production

Les source maps en production divulguent votre code source original. Désactivez-les sauf si vous les téléchargez vers un traqueur d'erreurs (Sentry, Bugsnag) et les supprimez localement ensuite :

build: {
  sourcemap: false,                                  // par défaut — gardez-le ainsi
}

Liste de vérification .gitignore

  • .env.local, .env.*.local — remplacements de secrets locaux
  • dist/ — sortie du build
  • node_modules/.vite — cache de pré-bundling (les entrées obsolètes provoquent des erreurs fantômes)

Proxy serveur

// vite.config.ts — server.proxy
server: {
  proxy: {
    '/foo': 'http://localhost:4567',                    // forme courte en string

    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,                               // nécessaire pour les backends à hôte virtuel
      rewrite: (path) => path.replace(/^\/api/, ''),
    },
  },
}

Pour le proxy WebSocket, ajoutez ws: true à la configuration de la route.

Optimisation du build

Chunks manuels

// vite.config.ts — build.rolldownOptions
build: {
  rolldownOptions: {
    output: {
      // Forme objet : grouper des packages spécifiques
      manualChunks: {
        'react-vendor': ['react', 'react-dom'],
        'ui-vendor': ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
      },
    },
  },
}
// Forme fonction : diviser par heuristique
manualChunks(id) {
  if (id.includes('node_modules/react')) return 'react-vendor'
  if (id.includes('node_modules')) return 'vendor'
}

Performances

Évitez les fichiers barils

Les fichiers barils (index.ts réexportant tout depuis un répertoire) forcent Vite à charger chaque fichier réexporté même lorsque vous importez un seul symbole. C'est le ralentissement n°1 du serveur de développement signalé par la documentation officielle.

// MAUVAIS — importer un util force Vite à charger tout le baril
import { slash } from '@/utils'

// BON — import direct, un seul fichier est chargé
import { slash } from '@/utils/slash'

Soyez explicite avec les extensions d'import

Chaque extension implicite force jusqu'à 6 vérifications du système de fichiers via resolve.extensions. Dans les grandes bases de code, cela s'additionne.

// MAUVAIS
import Component from './Component'

// BON
import Component from './Component.tsx'

Réduisez allowImportingTsExtensions de tsconfig.json et resolve.extensions aux seules extensions que vous utilisez réellement.

Pré-chauffez les routes à chemin chaud

server.warmup.clientFiles pré-transforme les entrées chaudes connues avant que le navigateur ne les demande — éliminant la cascade de requêtes de chargement à froid sur les grandes applications.

// vite.config.ts
server: {
  warmup: {
    clientFiles: ['./src/main.tsx', './src/routes/**/*.tsx'],
  },
}

Profilage des serveurs de développement lents

Quand vite dev semble lent, commencez par vite --profile, interagissez avec l'application, puis appuyez sur p+entrée pour enregistrer un fichier .cpuprofile. Chargez-le dans Speedscope pour trouver quels plugins consomment du temps — généralement les hooks buildStart, config ou configResolved dans les plugins communautaires.

Mode bibliothèque

Lors de la publication d'un package npm, utilisez build.lib. Deux pièges sont plus importants que le détail de la configuration :

  1. Les types ne sont pas émis — ajoutez vite-plugin-dts ou exécutez tsc --emitDeclarationOnly séparément.
  2. Les dépendances de pair DOIVENT être externalisées — les pairs non listés sont empaquetés dans votre bibliothèque, provoquant des erreurs de double exécution chez les consommateurs.
// vite.config.ts
build: {
  lib: {
    entry: 'src/index.ts',
    formats: ['es', 'cjs'],
    fileName: (format) => `my-lib.${format}.js`,
  },
  rolldownOptions: {
    external: ['react', 'react-dom', 'react/jsx-runtime'],  // chaque dépendance de pair
  },
}

Externalisations SSR

Les configurations nues createServer({ middlewareMode: true }) sont du ressort des auteurs de framework. La plupart des applications devraient utiliser Nuxt, Remix, SvelteKit, Astro ou TanStack Start à la place. Ce que vous modifierez en tant qu'utilisateur de framework, c'est la configuration des externalisations lorsque des dépendances cassent en SSR :

// vite.config.ts — options ssr
ssr: {
  external: ['node-native-package'],           // conserver en require() dans le bundle SSR
  noExternal: ['esm-only-package'],            // forcer l'empaquetage dans la sortie SSR (corrige la plupart des erreurs SSR)
  target: 'node',                              // 'node' ou 'webworker'
}

Pré-bundling des dépendances

Vite pré-empaquète les dépendances pour convertir CJS/UMD en ESM et réduire le nombre de requêtes.

// vite.config.ts — optimizeDeps
optimizeDeps: {
  include: [
    'lodash-es',                              // forcer le pré-bundling des dépendances lourdes connues
    'cjs-package',                            // dépendances CJS qui causent des problèmes d'interopérabilité
    'deep-lib/components/**',                 // glob pour les imports profonds
  ],
  exclude: ['local-esm-package'],             // doit être un ESM valide s'il est exclu
  force: true,                                // ignorer le cache, ré-optimiser (débogage temporaire)
}

Pièges courants

Le développement ne correspond pas au build

Le développement utilise esbuild/Rolldown pour les transformations ; le build utilise Rolldown pour l'empaquetage. Les bibliothèques CJS peuvent se comporter différemment entre les deux. Vérifiez toujours avec vite build && vite preview avant de déployer.

Chunks obsolètes après le déploiement

Les nouveaux builds produisent de nouveaux hachages de chunks. Les utilisateurs avec des sessions actives demandent d'anciens noms de fichiers qui n'existent plus. Vite n'a pas de solution intégrée. Atténuations :

  • Gardez les anciens fichiers dist/assets/ actifs pendant une fenêtre de déploiement
  • Attrapez les erreurs d'import dynamique dans votre routeur et forcez un rechargement de page

Docker et conteneurs

Vite se lie à localhost par défaut, ce qui est inaccessible depuis l'extérieur d'un conteneur :

// vite.config.ts — configuration Docker/conteneur
server: {
  host: true,                                  // lier 0.0.0.0
  hmr: { clientPort: 3000 },                   // si derrière un proxy inverse
}

Accès aux fichiers dans un monorepo

Vite restreint le service de fichiers à la racine du projet. Les packages en dehors de la racine sont bloqués :

// vite.config.ts — accès aux fichiers dans un monorepo
server: {
  fs: {
    allow: ['..'],                             // autoriser le répertoire parent (racine de l'espace de travail)
  },
}

Anti-patrons

// MAUVAIS : Définir envPrefix à '' expose TOUTES les variables d'environnement (y compris les secrets) au client
envPrefix: ''

// MAUVAIS : Supposer que require() fonctionne en ESM — utilisez import à la place

Débogage

Erreurs de build

# Afficher la sortie détaillée du build
vite build --debug

# Vérifier les fichiers résolus et les transformations appliquées
npx vite-plugin-inspect

Problèmes de pré-bundling

# Effacer le cache de pré-bundling et forcer la ré-optimisation
rm -rf node_modules/.vite
vite --force

Vérification des versions

npx vite --version        # Vite CLI
node -e "console.log(require('vite/package.json').version)"  # Version du package

Ressources supplémentaires

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

Skills associés