Communitygithub.com

vite-patterns

Vite-Build-Tool-Patterns inklusive Konfiguration, Plugins, HMR, Umgebungsvariablen, Proxy-Setup, SSR, Library-Modus, Abhängigkeits-Vorab-Bündelung und Build-Optimierung. Aktivieren bei Arbeit mit vite.config.ts, Vite-Plugins oder Vite-basierten Projekten.

Was ist vite-patterns?

Diese Fähigkeit namens 'vite-patterns' ist eine umfassende Sammlung von Best Practices und Codebeispielen für Vite 8+ Projekte. Sie deckt alle wichtigen Aspekte des Build-Tools ab: von der Konfiguration der `vite.config.ts` über Plugins, HMR, Umgebungsvariablen und Proxy-Setup bis hin zur Build-Optimierung, Library-Modus, SSR und Dependency Pre-Bundling. Basierend auf der SKILL.md-Dokumentation liefert sie konkrete, sofort nutzbare Beispiele und zeigt häufige Fallstricke auf, wie z.B. die fehlende Typprüfung im Build (`vite-plugin-checker`), die Sicherheitsproblematik von `VITE_`-Variablen (kein Sicherheitsmechanismus) oder Performance-Probleme durch Barrel-Dateien. Die Fähigkeit ist plattformunabhängig und kann in jedem Vite-basierten Projekt (React, Vue, Svelte, etc.) eingesetzt werden. Sie erklärt die Funktionsweise von Dev-Modus (ESM ohne Bündelung) und Build-Modus (Rolldown/Rollup) sowie wichtige Unterschiede, z.B. zwischen Dev- und Build-Verhalten bei CJS-Bibliotheken.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/vite-patterns

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Vite Patterns

Build-Tool- und Dev-Server-Patterns für Vite 8+ Projekte. Deckt Konfiguration, Umgebungsvariablen, Proxy-Setup, Library-Modus, Abhängigkeits-Vorab-Bündelung und häufige Produktionsfallstricke ab.

Wann verwenden

  • Konfigurieren von vite.config.ts oder vite.config.js
  • Einrichten von Umgebungsvariablen oder .env-Dateien
  • Konfigurieren des Dev-Server-Proxys für API-Backends
  • Optimieren der Build-Ausgabe (Chunks, Minifizierung, Assets)
  • Veröffentlichen von Bibliotheken mit build.lib
  • Fehlersuche bei Abhängigkeits-Vorab-Bündelung oder CJS/ESM-Interop
  • Debuggen von HMR, Dev-Server oder Build-Fehlern
  • Auswählen oder Anordnen von Vite-Plugins

Wie es funktioniert

  • Dev-Modus dient Quelldateien als natives ESM — keine Bündelung. Transformationen erfolgen on-demand pro Modulanfrage, daher sind Kaltstarts schnell und HMR präzise.
  • Build-Modus verwendet Rolldown (v7+) oder Rollup (v5–v6), um die App für die Produktion mit Tree-Shaking, Code-Splitting und Oxc-basierter Minifizierung zu bündeln.
  • Dependency Pre-Bundling konvertiert CJS/UMD-Abhängigkeiten einmalig in ESM via esbuild und cached das Ergebnis unter node_modules/.vite, sodass nachfolgende Starts die Arbeit überspringen.
  • Plugins teilen eine einheitliche Schnittstelle für Dev und Build — das gleiche Plugin-Objekt funktioniert sowohl für die On-Demand-Transformationen des Dev-Servers als auch für die Produktions-Pipeline.
  • Umgebungsvariablen werden zur Build-Zeit statisch inline eingefügt. Mit VITE_-präfixierte Variablen werden zu öffentlichen Konstanten im Bundle; alles ohne Präfix ist für Client-Code unsichtbar.

Beispiele

Konfigurationsstruktur

Einfache Konfiguration

// 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 },
  },
})

Bedingte Konfiguration

// 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())   // Nur VITE_-Präfix (sicher)

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

Wichtige Konfigurationsoptionen

SchlüsselStandardBeschreibung
root'.'Projektstamm (wo index.html liegt)
base'/'Öffentlicher Basispfad für bereitgestellte Assets
envPrefix'VITE_'Präfix für Client-exponierte Umgebungsvariablen
build.outDir'dist'Ausgabeverzeichnis
build.minify'oxc'Minifizierer ('oxc', 'terser' oder false)
build.sourcemapfalsetrue, 'inline' oder 'hidden'

Plugins

Essentielle Plugins

Die meisten Plugin-Anforderungen werden von einer Handvoll gut gewarteter Pakete abgedeckt. Greifen Sie zu diesen, bevor Sie eigene schreiben.

PluginZweckWann verwenden
@vitejs/plugin-react-swcReact HMR + Fast Refresh via SWCStandard für React-Apps (schneller als Babel-Variante)
@vitejs/plugin-reactReact HMR + Fast Refresh via BabelNur wenn Sie Babel-Plugins benötigen (Emotion, MobX Decorators)
@vitejs/plugin-vueVue 3 SFC-UnterstützungVue-Apps
vite-plugin-checkerFührt tsc + ESLint in einem Worker-Thread mit HMR-Overlay ausJede TypeScript-App — Vite führt KEINE Typprüfung während vite build durch
vite-tsconfig-pathsBerücksichtigt Aliasse aus tsconfig.json pathsImmer wenn Sie bereits Aliasse in tsconfig.json haben
vite-plugin-dtsErzeugt .d.ts-Dateien im Library-ModusBeim Veröffentlichen von TypeScript-Bibliotheken
vite-plugin-svgrImportiert SVGs als React-KomponentenReact-Apps, die SVGs als Komponenten verwenden
rollup-plugin-visualizerBundle-Treemap/Sunburst-BerichtRegelmäßige Bundle-Größen-Audits (mit enforce: 'post' verwenden)
vite-plugin-pwaZero-Config PWA + WorkboxOffline-fähige Apps

Wichtiger Hinweis: vite build transpiliert, führt aber KEINE Typprüfung durch. Typfehler gelangen stillschweigend in die Produktion, es sei denn, Sie fügen vite-plugin-checker hinzu oder führen tsc --noEmit in CI aus.

Erstellen eigener Plugins

Das Erstellen eigener Plugins ist selten — die meisten Anforderungen werden von vorhandenen Plugins abgedeckt. Wenn Sie doch eines benötigen, beginnen Sie inline in vite.config.ts und extrahieren Sie es nur bei Wiederverwendung.

// vite.config.ts — minimales Inline-Plugin
function myPlugin(): Plugin {
  return {
    name: 'my-plugin',                       // erforderlich, muss eindeutig sein
    enforce: 'pre',                           // 'pre' | 'post' (optional)
    apply: 'build',                           // 'build' | 'serve' (optional)
    transform(code, id) {
      if (!id.endsWith('.custom')) return
      return { code: transformCustom(code), map: null }
    },
  }
}

Wichtige Hooks: transform (Quelle modifizieren), resolveId + load (virtuelle Module), transformIndexHtml (in HTML einfügen), configureServer (Dev-Middleware hinzufügen), hotUpdate (benutzerdefiniertes HMR — ersetzt das in v7+ deprecated handleHotUpdate).

Virtuelle Module verwenden die \0-Präfix-Konvention — resolveId gibt '\0virtual:my-id' zurück, sodass andere Plugins es überspringen. Benutzercode importiert 'virtual:my-id'.

Die vollständige Plugin-API finden Sie unter vite.dev/guide/api-plugin. Verwenden Sie vite-plugin-inspect während der Entwicklung, um die Transform-Pipeline zu debuggen.

HMR API

Framework-Plugins (@vitejs/plugin-react, @vitejs/plugin-vue usw.) kümmern sich automatisch um HMR. Greifen Sie nur dann direkt auf import.meta.hot zu, wenn Sie benutzerdefinierte Zustandsspeicher, Entwicklerwerkzeuge oder Framework-agnostische Dienstprogramme erstellen, die den Zustand über Aktualisierungen hinweg beibehalten müssen.

// src/store.ts — manuelles HMR für ein Vanilla-Modul
if (import.meta.hot) {
  // Zustand über Aktualisierungen hinweg beibehalten (MUSS mutiert, NIEMALS .data neu zugewiesen werden)
  import.meta.hot.data.count = import.meta.hot.data.count ?? 0

  // Nebenwirkungen bereinigen, bevor das Modul ersetzt wird
  import.meta.hot.dispose((data) => clearInterval(data.intervalId))

  // Eigene Aktualisierungen dieses Moduls akzeptieren
  import.meta.hot.accept()
}

Der gesamte import.meta.hot-Code wird in Produktions-Builds durch Tree-Shaking entfernt — keine Guard-Entfernung erforderlich.

Umgebungsvariablen

Vite lädt .env, .env.local, .env.[mode] und .env.[mode].local in dieser Reihenfolge (spätere überschreiben frühere); *.local-Dateien sind gitignored und für lokale Geheimnisse gedacht.

Clientseitiger Zugriff

Nur VITE_-präfixierte Variablen sind für Clientcode sichtbar:

import.meta.env.VITE_API_URL   // string
import.meta.env.MODE            // 'development' | 'production' | custom
import.meta.env.BASE_URL        // base config value
import.meta.env.DEV             // boolean
import.meta.env.PROD            // boolean
import.meta.env.SSR             // boolean

Verwendung von Env in der Konfiguration

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

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd())          // Nur VITE_-Präfix (sicher)
  return {
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  }
})

Sicherheit

VITE_-Präfix ist KEINE Sicherheitsgrenze

Jede Variable mit dem Präfix VITE_ wird zur Build-Zeit statisch in das Client-Bundle eingefügt. Minifizierung, Base64-Kodierung und Deaktivieren von Source Maps verbergen sie NICHT. Ein entschlossener Angreifer kann jede VITE_-Variable aus dem ausgelieferten JavaScript extrahieren.

Regel: Nur öffentliche Werte (API-URLs, Feature-Flags, öffentliche Schlüssel) kommen in VITE_-Variablen. Geheimnisse (API-Tokens, Datenbank-URLs, private Schlüssel) MÜSSEN serverseitig hinter einer API oder serverlosen Funktion leben.

Die loadEnv('')-Falle

// SCHLECHT: Übergabe von '' als drittes Argument lädt ALLE Umgebungsvariablen – einschließlich Server-Geheimnisse –
// und macht sie verfügbar, um via `define` in Client-Code eingefügt zu werden.
const env = loadEnv(mode, process.cwd(), '')

// GUT: Explizite Präfixliste
const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_'])

Source Maps in der Produktion

Produktions-Source Maps geben Ihren ursprünglichen Quellcode preis. Deaktivieren Sie sie, es sei denn, Sie laden sie zu einem Fehler-Tracker (Sentry, Bugsnag) hoch und löschen sie danach lokal:

build: {
  sourcemap: false,                                  // Standard – so belassen
}

.gitignore-Checkliste

  • .env.local, .env.*.local — lokale Geheimnis-Überschreibungen
  • dist/ — Build-Ausgabe
  • node_modules/.vite — Vorab-Bündelungs-Cache (veraltete Einträge verursachen Phantomfehler)

Server Proxy

// vite.config.ts — server.proxy
server: {
  proxy: {
    '/foo': 'http://localhost:4567',                    // String-Kurzform

    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,                               // erforderlich für virtuelle Host-Backends
      rewrite: (path) => path.replace(/^\/api/, ''),
    },
  },
}

Für WebSocket-Proxying fügen Sie ws: true zur Routenkonfiguration hinzu.

Build-Optimierung

Manuelle Chunks

// vite.config.ts — build.rolldownOptions
build: {
  rolldownOptions: {
    output: {
      // Objektform: bestimmte Pakete gruppieren
      manualChunks: {
        'react-vendor': ['react', 'react-dom'],
        'ui-vendor': ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
      },
    },
  },
}
// Funktionsform: nach Heuristik aufteilen
manualChunks(id) {
  if (id.includes('node_modules/react')) return 'react-vendor'
  if (id.includes('node_modules')) return 'vendor'
}

Leistung

Barrel-Dateien vermeiden

Barrel-Dateien (index.ts, die alles aus einem Verzeichnis re-exportieren) zwingen Vite, jede re-exportierte Datei zu laden, selbst wenn Sie nur ein einzelnes Symbol importieren. Dies ist die Nr. 1 der Verlangsamung des Dev-Servers, die in der offiziellen Dokumentation genannt wird.

// SCHLECHT — Das Importieren eines einzigen Utils zwingt Vite, das gesamte Barrel zu laden
import { slash } from '@/utils'

// GUT — Direkter Import, nur die eine Datei wird geladen
import { slash } from '@/utils/slash'

Seien Sie explizit mit Import-Erweiterungen

Jede implizite Erweiterung erzwingt bis zu 6 Dateisystem-Überprüfungen via resolve.extensions. In großen Codebasen summiert sich das.

// SCHLECHT
import Component from './Component'

// GUT
import Component from './Component.tsx'

Schränken Sie tsconfig.json allowImportingTsExtensions + resolve.extensions auf nur die Erweiterungen ein, die Sie tatsächlich verwenden.

Aufwärmen von Hot-Path-Routen

server.warmup.clientFiles transformiert bekannte heiße Einträge vorab, bevor der Browser sie anfordert — dies eliminiert den Kaltstart-Wasserfall von Anfragen bei großen Apps.

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

Profiling langsamer Dev-Server

Wenn sich vite dev langsam anfühlt, beginnen Sie mit vite --profile, interagieren Sie mit der App, drücken Sie dann p+Enter, um eine .cpuprofile-Datei zu speichern. Laden Sie sie in Speedscope, um herauszufinden, welche Plugins Zeit fressen — normalerweise die Hooks buildStart, config oder configResolved in Community-Plugins.

Library-Modus

Wenn Sie ein npm-Paket veröffentlichen, verwenden Sie build.lib. Zwei Fallstricke sind wichtiger als die Konfigurationsdetails:

  1. Typen werden nicht ausgegeben — fügen Sie vite-plugin-dts hinzu oder führen Sie tsc --emitDeclarationOnly separat aus.
  2. Peer-Abhängigkeiten MÜSSEN externalisiert werden — nicht aufgeführte Peers werden in Ihre Bibliothek gebündelt, was bei Benutzern doppelte Laufzeitfehler verursacht.
// 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'],  // jede Peer-Abhängigkeit
  },
}

SSR Externalisierungen

Reine createServer({ middlewareMode: true })-Setups sind Framework-Autoren-Territorium. Die meisten Apps sollten stattdessen Nuxt, Remix, SvelteKit, Astro oder TanStack Start verwenden. Was Sie als Framework-Benutzer anpassen werden, ist die Externalisierungskonfiguration, wenn Abhängigkeiten in SSR brechen:

// vite.config.ts — ssr-Optionen
ssr: {
  external: ['node-native-package'],           // als require() im SSR-Bundle belassen
  noExternal: ['esm-only-package'],            // erzwungen in SSR-Ausgabe bündeln (behebt die meisten SSR-Fehler)
  target: 'node',                              // 'node' oder 'webworker'
}

Abhängigkeits-Vorab-Bündelung

Vite bündelt Abhängigkeiten vor, um CJS/UMD in ESM zu konvertieren und die Anzahl der Anfragen zu reduzieren.

// vite.config.ts — optimizeDeps
optimizeDeps: {
  include: [
    'lodash-es',                              // bekannte schwere Abhängigkeiten erzwingen
    'cjs-package',                            // CJS-Abhängigkeiten, die Interop-Probleme verursachen
    'deep-lib/components/**',                 // Glob für tiefe Imports
  ],
  exclude: ['local-esm-package'],             // muss gültiges ESM sein, wenn ausgeschlossen
  force: true,                                // Cache ignorieren, neu optimieren (temporäres Debugging)
}

Häufige Fallstricke

Dev stimmt nicht mit Build überein

Dev verwendet esbuild/Rolldown für Transformationen; Build verwendet Rolldown für die Bündelung. CJS-Bibliotheken können sich zwischen beiden unterschiedlich verhalten. Überprüfen Sie immer mit vite build && vite preview vor der Bereitstellung.

Veraltete Chunks nach der Bereitstellung

Neue Builds erzeugen neue Chunk-Hashes. Benutzer mit aktiven Sitzungen fordern alte Dateinamen an, die nicht mehr existieren. Vite hat keine integrierte Lösung. Minderungsmaßnahmen:

  • Alte dist/assets/-Dateien für ein Bereitstellungsfenster aktiv lassen
  • Dynamische Importfehler in Ihrem Router abfangen und einen Seitenneuladen erzwingen

Docker und Container

Vite bindet standardmäßig an localhost, was von außerhalb eines Containers nicht erreichbar ist:

// vite.config.ts — Docker/Container-Setup
server: {
  host: true,                                  // an 0.0.0.0 binden
  hmr: { clientPort: 3000 },                   // falls hinter einem Reverse-Proxy
}

Monorepo-Dateizugriff

Vite beschränkt das Bereitstellen von Dateien auf das Projektstammverzeichnis. Pakete außerhalb des Stammverzeichnisses werden blockiert:

// vite.config.ts — Monorepo-Dateizugriff
server: {
  fs: {
    allow: ['..'],                             // übergeordnetes Verzeichnis erlauben (Workspace-Stamm)
  },
}

Anti-Patterns

// SCHLECHT: Das Setzen von envPrefix auf '' legt ALLE Umgebungsvariablen (einschließlich Geheimnisse) offen
envPrefix: ''

// SCHLECHT: Annahme, dass require() im Browser funktioniert

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/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

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.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Verwandte Skills