# Vite Administrator & Developer Guide

Vite v8.0.8 is a native-ESM-powered web development build tool created by Evan You and maintained under the MIT License. It provides an instant dev server with hot module replacement (HMR) and a highly optimized production build pipeline powered by Rolldown. This guide covers the complete architecture, configuration surface, deployment considerations, security posture, and internal mechanics that administrators, platform engineers, and contributing developers need to operate and extend Vite at scale.

---

## 1. Architecture Overview

### 1.1 Monorepo Structure

Vite ships as a pnpm v10.33.0 workspace monorepo containing three publishable packages:

| Package | Version | Purpose |
|---------|---------|---------|
| `packages/vite` | 8.0.8 | Core dev server + production bundler |
| `packages/create-vite` | 9.0.4 | Project scaffolding CLI (`npm create vite`) |
| `packages/plugin-legacy` | 8.0.1 | Legacy browser support via Babel + SystemJS |

```
packages/
├── vite/                    # Core package
│   ├── bin/vite.js         # CLI entry point
│   ├── src/
│   │   ├── node/           # Node.js server + build logic
│   │   │   ├── cli.ts      # CLI command definitions (cac-based)
│   │   │   ├── index.ts    # Public API exports
│   │   │   ├── server/     # Dev server (connect-based)
│   │   │   │   ├── index.ts
│   │   │   │   ├── environments/
│   │   │   │   └── middlewares/
│   │   │   ├── plugins/    # 29 built-in plugins (~81K chars)
│   │   │   ├── optimizer/  # Dependency pre-bundling
│   │   │   ├── ssr/        # Server-side rendering
│   │   │   │   └── runtime/ # Module runner
│   │   │   └── __tests__/
│   │   ├── client/         # Browser-side HMR client + env injection
│   │   ├── module-runner/  # Standalone module runner (SSR/Workers)
│   │   ├── shared/         # Shared utilities (node + client)
│   │   └── types/          # Internal TypeScript type definitions
│   ├── types/              # Public type definitions
│   │   └── internal/       # Internal-only types
│   ├── client.d.ts         # Client-side ambient type declarations
│   ├── rolldown.config.ts  # Self-bundle configuration
│   └── rolldown.dts.config.ts # Type generation config
├── create-vite/            # Scaffolding tool
│   ├── src/index.ts        # CLI logic
│   └── template-*/         # 20+ project templates
└── plugin-legacy/          # Legacy browser plugin
    └── src/index.ts        # Babel + SystemJS transforms
```

### 1.2 Technology Stack

| Component | Technology | Version |
|-----------|-----------|---------|
| Production bundler | Rolldown | 1.0.0-rc.16 |
| Self-build bundler | Rolldown | 1.0.0-rc.16 |
| JS transform | oxc / esbuild | esbuild ^0.28.0 |
| CSS processing | PostCSS + LightningCSS | postcss ^8.5.9, lightningcss ^1.32.0 |
| Dev server | connect | ^3.7.0 |
| File watching | chokidar | ^3.6.0 |
| Module analysis | es-module-lexer | ^1.7.0 |
| Glob matching | picomatch + tinyglobby | picomatch ^4.0.4 |
| Unit testing | Vitest | ^4.1.4 |
| E2E testing | Playwright (Chromium) | ^1.59.1 |
| TypeScript | TypeScript | ~6.0.2 |
| Linting | ESLint | ^9.39.4 |
| Formatting | oxfmt | ^0.44.0 |

### 1.3 Runtime Dependencies

The `packages/vite` package has an intentionally minimal runtime dependency footprint:

**Runtime (installed by consumers):** lightningcss, picomatch, postcss, rolldown, tinyglobby

**Optional:** fsevents (macOS file system events — automatically skipped on non-Darwin platforms)

**Bundled devDependencies (compiled into dist):** cac (CLI framework), connect, chokidar, dotenv/dotenv-expand, es-module-lexer, esbuild, escape-html, magic-string, postcss-import, postcss-modules, ws (WebSocket), open, strip-literal, @rollup/plugin-alias, @rollup/pluginutils, cors, etag, http-proxy, launch-editor-middleware, mrmime, parse5, picocolors, sirv, artichokie, @vitest/utils, @vitejs/devtools

> [!IMPORTANT]
> The distinction between runtime and bundled dependencies matters for deployment. Runtime dependencies must be installed in the consuming project's `node_modules`. Bundled dependencies are compiled into Vite's `dist/` during the Vite build process itself and do not need separate installation.

### 1.4 Package Exports Map

The `packages/vite` package exposes a carefully controlled public API surface through its `exports` field:

| Export Path | Target | Purpose |
|-------------|--------|---------|
| `.` | `./dist/node/index.js` | Main programmatic API |
| `./client` | `client.d.ts` (types only) | Client-side type declarations |
| `./module-runner` | `./dist/node/module-runner.js` | Standalone module runner |
| `./internal` | `./dist/node/internal.js` | Internal APIs (unstable) |
| `./dist/client/*` | Client files | Browser-side HMR client |
| `./types/*` | Type definitions | Public TypeScript types |

### 1.5 Dual-Mode Architecture

Vite operates in two fundamentally different modes, each with distinct code paths:

**Development (`vite` / `vite dev` / `vite serve`):**
- connect-based HTTP server serves files on demand
- Native ESM — no bundling of application code
- Dependency pre-bundling via the optimizer (Rolldown) for CommonJS/UMD compatibility and request waterfall elimination
- WebSocket-based HMR for instant updates
- Module graph tracks dependencies for surgical invalidation
- Environment API enables multi-target dev (browser client, SSR, workers)

**Production (`vite build`):**
- Full application bundle via Rolldown
- Code splitting, tree shaking, minification
- CSS extraction and code splitting
- Asset hashing for long-term caching
- HTML processing with script/style injection
- Optional legacy browser output via plugin-legacy

---

## 2. System Requirements

### 2.1 Node.js

```
Node.js ^20.19.0 || >=22.12.0
```

> [!WARNING]
> Node.js 21.x and versions below 20.19.0 are explicitly unsupported. The version constraint is enforced at the engine level in `package.json`. Odd-numbered Node.js releases (21, 23) are never targeted because they are non-LTS.

### 2.2 Package Manager

The monorepo requires **pnpm v10.33.0** for workspace management. The version is pinned via `packageManager` in the root `package.json` and enforced by Corepack.

```bash
corepack enable
corepack prepare pnpm@10.33.0 --activate
```

### 2.3 Operating System

Vite runs on Linux, macOS, and Windows. Platform-specific considerations:

| Platform | Notes |
|----------|-------|
| macOS | `fsevents` optional dependency provides superior file-watching performance |
| Linux | inotify watches may need tuning for large projects (`fs.inotify.max_user_watches`) |
| Windows | Forward slashes in config paths are normalized; WSL2 recommended for best performance |

### 2.4 Build Requirements (Contributing to Vite Itself)

To build the Vite source from the monorepo:

```bash
# Clone and install
git clone https://github.com/vitejs/vite.git
cd vite
pnpm install

# Build all packages
pnpm build

# Dev mode (watch) for all packages
pnpm dev
```

Additional tools for development:

| Tool | Purpose | Installation |
|------|---------|-------------|
| Playwright | E2E browser tests | `pnpm exec playwright install chromium` |
| Git hooks | Pre-commit lint | Automatic via `simple-git-hooks` |

### 2.5 Browser Support

**Default modern build targets:** Browsers supporting native ESM, native ESM dynamic import, and `import.meta`.

**With plugin-legacy:** Configurable via browserslist. Default modern polyfill targets: `edge>=105, firefox>=106, chrome>=105, safari>=16.4`.

---

## 3. Configuration Reference

### 3.1 Configuration File Resolution

Vite resolves configuration from these locations, in order:

1. `vite.config.ts` (or `.js`, `.mjs`, `.mts`, `.cjs`, `.cts`)
2. Inline config passed via `--config` CLI flag
3. Programmatic API (`createServer()`, `build()`)

The config file is transpiled on the fly using esbuild, so TypeScript is supported natively without pre-compilation.

```typescript
// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  // configuration options
})
```

Conditional configuration via function form:

```typescript
export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => {
  if (command === 'serve') {
    return { /* dev-specific config */ }
  } else {
    return { /* build-specific config */ }
  }
})
```

Async configuration:

```typescript
export default defineConfig(async ({ command, mode }) => {
  const data = await fetchSomeConfig()
  return { /* config using data */ }
})
```

### 3.2 Core Configuration Options

#### Shared Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `root` | `string` | `process.cwd()` | Project root directory |
| `base` | `string` | `'/'` | Public base path |
| `mode` | `string` | `'development'` (serve) / `'production'` (build) | Mode for `.env` loading |
| `define` | `Record<string, any>` | — | Compile-time global constant replacements |
| `plugins` | `(Plugin \| Plugin[])[]` | `[]` | Plugin array |
| `publicDir` | `string \| false` | `'public'` | Static asset directory (copied as-is) |
| `cacheDir` | `string` | `'node_modules/.vite'` | Cache directory for pre-bundled deps |
| `resolve.alias` | `Record<string, string> \| Array` | — | Path aliases |
| `resolve.extensions` | `string[]` | `['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']` | Extension resolution order |
| `resolve.conditions` | `string[]` | — | Additional export conditions |
| `css.modules` | `CSSModulesOptions` | — | CSS Modules configuration |
| `css.postcss` | `string \| PostCSSConfig` | — | PostCSS config (inline or path) |
| `css.preprocessorOptions` | `Record<string, object>` | — | Pre-processor options (sass, less, stylus) |
| `css.lightningcss` | `LightningCSSOptions` | — | LightningCSS transformer config |
| `json.stringify` | `boolean` | `false` | JSON imports as strings for performance |
| `esbuild` | `ESBuildOptions \| false` | — | esbuild transform options |
| `assetsInclude` | `string \| RegExp \| (string \| RegExp)[]` | — | Additional file types to treat as assets |
| `logLevel` | `'info' \| 'warn' \| 'error' \| 'silent'` | `'info'` | Console output level |
| `envDir` | `string` | `root` | Directory to load `.env` files from |
| `envPrefix` | `string \| string[]` | `'VITE_'` | Env variables exposed to client code |

#### Server Options (`server.*`)

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `server.host` | `string \| boolean` | `'localhost'` | Bind address (`true` = `0.0.0.0`) |
| `server.port` | `number` | `5173` | Dev server port |
| `server.strictPort` | `boolean` | `false` | Exit if port is taken |
| `server.https` | `ServerOptions` | — | TLS configuration |
| `server.open` | `boolean \| string` | `false` | Open browser on start |
| `server.proxy` | `Record<string, ProxyOptions>` | — | Proxy rules (uses `http-proxy`) |
| `server.cors` | `boolean \| CorsOptions` | — | CORS configuration |
| `server.headers` | `Record<string, string>` | — | Custom response headers |
| `server.hmr` | `boolean \| HmrOptions` | — | HMR configuration |
| `server.watch` | `WatchOptions` | — | chokidar file watcher options |
| `server.middlewareMode` | `boolean` | `false` | Create server without HTTP listener |
| `server.fs.strict` | `boolean` | `true` | Restrict file access to workspace |
| `server.fs.allow` | `string[]` | — | Additional allowed directories |
| `server.fs.deny` | `string[]` | `['.env', '.env.*', '*.{crt,pem}', '**/.git/**']` | Denied file patterns |
| `server.warmup.clientFiles` | `string[]` | — | Files to pre-transform on startup |
| `server.warmup.ssrFiles` | `string[]` | — | SSR files to pre-transform |

#### Build Options (`build.*`)

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `build.target` | `string \| string[]` | `'modules'` | Browser compatibility target |
| `build.outDir` | `string` | `'dist'` | Output directory |
| `build.assetsDir` | `string` | `'assets'` | Assets subdirectory within outDir |
| `build.assetsInlineLimit` | `number \| ((filePath, content) => boolean)` | `4096` (4KB) | Inline assets below this size as base64 |
| `build.cssCodeSplit` | `boolean` | `true` | Enable CSS code splitting |
| `build.cssTarget` | `string \| string[]` | same as `build.target` | CSS browser target |
| `build.cssMinify` | `boolean \| 'lightningcss'` | same as `build.minify` | CSS minification |
| `build.sourcemap` | `boolean \| 'inline' \| 'hidden'` | `false` | Source map generation |
| `build.rolldownOptions` | `RolldownOptions` | — | Pass-through to Rolldown |
| `build.lib` | `LibraryOptions` | — | Library mode configuration |
| `build.manifest` | `boolean \| string` | `false` | Generate manifest.json for backend integration |
| `build.ssrManifest` | `boolean \| string` | `false` | SSR manifest for preload directives |
| `build.ssr` | `boolean \| string` | `false` | SSR build |
| `build.minify` | `boolean \| 'oxc'` | `'oxc'` (non-lib) / `false` (lib+es) | Minification engine |
| `build.emptyOutDir` | `boolean` | `true` (if outDir is inside root) | Empty output directory before build |
| `build.copyPublicDir` | `boolean` | `true` | Copy public directory to outDir |
| `build.chunkSizeWarningLimit` | `number` | `500` (KB) | Chunk size warning threshold |

#### SSR Options (`ssr.*`)

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `ssr.external` | `string[] \| true` | — | Force-externalize dependencies |
| `ssr.noExternal` | `string \| RegExp \| (string \| RegExp)[] \| true` | — | Force-bundle dependencies |
| `ssr.target` | `'node' \| 'webworker'` | `'node'` | SSR target environment |
| `ssr.resolve.conditions` | `string[]` | — | SSR-specific resolve conditions |
| `ssr.resolve.externalConditions` | `string[]` | — | Conditions for externalized SSR deps |

#### Optimization Options (`optimizeDeps.*`)

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `optimizeDeps.entries` | `string \| string[]` | — | Custom entries for dep scanning |
| `optimizeDeps.exclude` | `string[]` | — | Dependencies to exclude from pre-bundling |
| `optimizeDeps.include` | `string[]` | — | Force include dependencies |
| `optimizeDeps.esbuildOptions` | `EsbuildBuildOptions` | — | esbuild options for dep optimization |
| `optimizeDeps.force` | `boolean` | `false` | Force re-bundle on server start |
| `optimizeDeps.holdUntilCrawlEnd` | `boolean` | `true` | Hold module loading until initial crawl completes |
| `optimizeDeps.needsInterop` | `string[]` | — | Force CJS interop for specific deps |

#### Preview Options (`preview.*`)

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `preview.host` | `string \| boolean` | `server.host` | Bind address |
| `preview.port` | `number` | `4173` | Preview server port |
| `preview.strictPort` | `boolean` | `server.strictPort` | Exit if port taken |
| `preview.https` | `ServerOptions` | `server.https` | TLS configuration |
| `preview.open` | `boolean \| string` | `server.open` | Open browser on start |
| `preview.proxy` | `Record<string, ProxyOptions>` | `server.proxy` | Proxy rules |
| `preview.cors` | `boolean \| CorsOptions` | `server.cors` | CORS configuration |
| `preview.headers` | `Record<string, string>` | `server.headers` | Response headers |

### 3.3 Environment Variables

#### `.env` File Loading

Vite loads `.env` files from the `envDir` directory (defaults to project root). Files are loaded in this order, with later files overriding earlier ones:

```
.env                # Always loaded
.env.local          # Always loaded, gitignored
.env.[mode]         # Loaded for specific mode
.env.[mode].local   # Loaded for specific mode, gitignored
```

Only variables prefixed with `VITE_` (configurable via `envPrefix`) are exposed to client-side code through `import.meta.env`.

#### Built-in Environment Variables

| Variable | Type | Description |
|----------|------|-------------|
| `import.meta.env.MODE` | `string` | Current mode (`development`, `production`, etc.) |
| `import.meta.env.BASE_URL` | `string` | Base URL from `base` config |
| `import.meta.env.PROD` | `boolean` | `true` in production mode |
| `import.meta.env.DEV` | `boolean` | `true` in development mode |
| `import.meta.env.SSR` | `boolean` | `true` during SSR |

> [!CAUTION]
> Never store secrets in `VITE_`-prefixed environment variables. They are statically replaced in client bundles and visible in shipped JavaScript. Use server-side environment variables (without the `VITE_` prefix) for API keys, database credentials, and other sensitive values.

### 3.4 CLI Commands

Vite's CLI is built on `cac` and provides these commands:

```bash
# Development server
vite [root]                    # Start dev server
vite dev [root]                # Alias for above
vite serve [root]              # Alias for above

# Production build
vite build [root]              # Build for production

# Preview production build
vite preview [root]            # Locally preview production build

# Dependency optimization
vite optimize [root]           # Pre-bundle dependencies
```

**Common CLI flags:**

| Flag | Applies To | Description |
|------|-----------|-------------|
| `--config <file>` | All | Config file path |
| `--base <path>` | All | Public base path |
| `--mode <mode>` | All | Set mode |
| `--logLevel <level>` | All | `info \| warn \| error \| silent` |
| `--clearScreen` | All | Allow/disable clear screen |
| `--host [host]` | dev, preview | Bind address |
| `--port <port>` | dev, preview | Port number |
| `--strictPort` | dev, preview | Exit if port taken |
| `--https` | dev, preview | Enable TLS |
| `--open [path]` | dev, preview | Open browser |
| `--cors` | dev, preview | Enable CORS |
| `--force` | dev | Force dependency re-optimization |
| `--outDir <dir>` | build | Output directory |
| `--sourcemap` | build | Generate source maps |
| `--minify [minifier]` | build | Enable/disable minification |
| `--emptyOutDir` | build | Empty output before build |
| `--watch` | build | Watch mode |

### 3.5 CSS Configuration Deep Dive

The CSS plugin is the largest built-in plugin (~3,500 lines) and warrants detailed configuration coverage.

#### CSS Modules

```typescript
export default defineConfig({
  css: {
    modules: {
      localsConvention: 'camelCaseOnly',
      scopeBehaviour: 'local',
      generateScopedName: '[name]__[local]___[hash:base64:5]',
      hashPrefix: '',
      globalModulePaths: [/global\.module\.css/],
    }
  }
})
```

Files matching `*.module.css`, `*.module.scss`, `*.module.sass`, `*.module.less`, `*.module.styl`, or `*.module.stylus` are automatically treated as CSS Modules.

#### Pre-processor Options

```typescript
export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        api: 'modern-compiler',       // Use modern Sass compiler API
        additionalData: `@use "vars" as *;`,
        includePaths: ['src/styles'],
      },
      less: {
        math: 'always',
        globalVars: { primary: '#1890ff' },
      },
      stylus: {
        define: { primary: '#1890ff' },
      },
    }
  }
})
```

#### LightningCSS as CSS Transformer

```typescript
import { Features } from 'lightningcss'

export default defineConfig({
  css: {
    transformer: 'lightningcss',
    lightningcss: {
      targets: { chrome: 105 },
      drafts: { customMedia: true },
      include: Features.Nesting,
    }
  }
})
```

> [!NOTE]
> When using LightningCSS as the transformer, PostCSS plugins are bypassed. This means tools like Tailwind CSS (which is a PostCSS plugin) require the default PostCSS transformer.

---

## 4. Deployment & Scaling

### 4.1 Production Build Output

A standard `vite build` produces:

```
dist/
├── index.html              # Processed HTML with injected scripts/styles
├── assets/
│   ├── index-[hash].js     # Main application bundle
│   ├── vendor-[hash].js    # Vendor chunk (if code-split)
│   ├── index-[hash].css    # Extracted CSS
│   └── logo-[hash].svg     # Hashed static assets
└── [public files]           # Copied from public/ directory
```

All asset filenames include content hashes for long-term cache busting. Configure your CDN/server with aggressive caching for `assets/`:

```nginx
location /assets/ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}
```

### 4.2 Build Manifest

For backend integration (Rails, Laravel, Django, etc.), enable the build manifest:

```typescript
export default defineConfig({
  build: {
    manifest: true,   // generates .vite/manifest.json
  }
})
```

The manifest maps original file names to their hashed output paths, enabling server-side rendering of correct `<script>` and `<link>` tags.

### 4.3 Multi-Page Application (MPA) Build

```typescript
import { resolve } from 'node:path'

export default defineConfig({
  build: {
    rolldownOptions: {
      input: {
        main: resolve(__dirname, 'index.html'),
        about: resolve(__dirname, 'about/index.html'),
        admin: resolve(__dirname, 'admin/index.html'),
      }
    }
  }
})
```

### 4.4 Library Mode

For building reusable libraries:

```typescript
export default defineConfig({
  build: {
    lib: {
      entry: resolve(__dirname, 'src/index.ts'),
      name: 'MyLib',
      fileName: 'my-lib',
      formats: ['es', 'cjs'],
    },
    rolldownOptions: {
      external: ['react', 'react-dom'],
    }
  }
})
```

> [!IMPORTANT]
> `@vitejs/plugin-legacy` does not support library mode. Library consumers are responsible for their own transpilation targets.

### 4.5 SSR Build

Server-side rendering builds produce a Node.js-compatible bundle:

```typescript
export default defineConfig({
  build: {
    ssr: 'src/entry-server.ts',
  }
})
```

Or via CLI: `vite build --ssr src/entry-server.ts`

SSR builds externalize `node_modules` by default, producing a bundle that `import()`s runtime dependencies rather than bundling them. Control this with `ssr.external` and `ssr.noExternal`.

### 4.6 Legacy Browser Support

For projects requiring IE11/older browser support, use `@vitejs/plugin-legacy`:

```typescript
import legacy from '@vitejs/plugin-legacy'

export default defineConfig({
  plugins: [
    legacy({
      targets: ['defaults', 'not IE 11'],
      // Automatic polyfill injection via core-js + regenerator-runtime
    })
  ]
})
```

This produces dual bundles:
- **Modern:** Native ESM for capable browsers
- **Legacy:** SystemJS-wrapped + transpiled via Babel for older browsers

The HTML output includes `<script type="module">` (modern) and `<script nomodule>` (legacy) tags for automatic browser-appropriate loading.

Modern polyfill targets: `edge>=105, firefox>=106, chrome>=105, safari>=16.4`.

### 4.7 Containerized Deployment

Example `Dockerfile` for building a Vite project:

```dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
```

Corresponding `nginx.conf` for SPA routing:

```nginx
server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html;

    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    location / {
        try_files $uri $uri/ /index.html;
    }
}
```

---

## 5. Operations

### 5.1 Development Server Management

#### Starting the Dev Server Programmatically

```typescript
import { createServer } from 'vite'

const server = await createServer({
  root: '/path/to/project',
  server: {
    port: 3000,
  },
})

await server.listen()
server.printUrls()
server.bindCLIShortcuts({ print: true })
```

#### Middleware Mode

For embedding Vite in an existing Express/Koa/Fastify server:

```typescript
import express from 'express'
import { createServer } from 'vite'

const app = express()
const vite = await createServer({
  server: { middlewareMode: true },
  appType: 'custom',
})

// Use Vite's connect middleware
app.use(vite.middlewares)

app.listen(3000)
```

#### Server Warmup

Pre-transform frequently used files to reduce initial page load latency:

```typescript
export default defineConfig({
  server: {
    warmup: {
      clientFiles: [
        './src/main.ts',
        './src/components/App.vue',
      ],
      ssrFiles: [
        './src/entry-server.ts',
      ],
    }
  }
})
```

### 5.2 Dependency Pre-Bundling (The Optimizer)

The optimizer is a critical subsystem that pre-bundles dependencies on first server start:

1. **Scans** entry points for bare import specifiers
2. **Bundles** each dependency into a single ESM file using Rolldown
3. **Caches** results in `node_modules/.vite/deps/`
4. **Invalidates** cache when `package.json`, lockfile, or config changes

Force re-optimization:

```bash
vite --force
# or
vite optimize
```

Programmatic invalidation:

```typescript
server.restart({ forceOptimize: true })
```

> [!TIP]
> If you encounter mysterious module errors during development, deleting `node_modules/.vite` and restarting the dev server often resolves stale cache issues. The `--force` flag accomplishes this automatically.

#### Controlling Pre-Bundling

```typescript
export default defineConfig({
  optimizeDeps: {
    // Force include deps that Vite can't auto-discover
    include: ['lodash-es', 'axios'],
    
    // Exclude deps that must remain un-bundled
    exclude: ['@vueuse/core'],
    
    // Hold module loading until initial crawl completes
    holdUntilCrawlEnd: true,
    
    // Force CJS interop for specific packages
    needsInterop: ['some-cjs-package'],
  }
})
```

### 5.3 Proxy Configuration

Forward API requests to a backend server during development:

```typescript
export default defineConfig({
  server: {
    proxy: {
      // String shorthand
      '/foo': 'http://localhost:4567',
      
      // With options
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
      
      // WebSocket proxy
      '/socket.io': {
        target: 'ws://localhost:5174',
        ws: true,
      },

      // Regex match
      '^/fallback/.*': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/fallback/, ''),
      },
    }
  }
})
```

### 5.4 Build Watch Mode

For development workflows that need continuous builds (e.g., backend-rendered apps):

```bash
vite build --watch
```

The watcher uses Rolldown's built-in watch mode and rebuilds on file changes.

### 5.5 Environment API (Multi-Environment)

Vite supports configuring multiple environments (browser, SSR, custom workers) with independent settings:

```typescript
export default defineConfig({
  environments: {
    client: {
      // Default browser environment
      build: {
        outDir: 'dist/client',
      },
    },
    ssr: {
      // SSR environment
      build: {
        outDir: 'dist/server',
        ssr: true,
      },
    },
    rsc: {
      // Custom environment (e.g., React Server Components)
      resolve: {
        conditions: ['react-server'],
      },
      build: {
        outDir: 'dist/rsc',
        ssr: true,
      },
    },
  },
})
```

Each environment maintains its own module graph, plugin pipeline, and optimization settings during development.

### 5.6 Debugging and Diagnostics

#### Debug Logging

Vite uses the `debug` package internally. Enable verbose logging with:

```bash
# All Vite debug logs
DEBUG="vite:*" vite

# Specific subsystems
DEBUG="vite:resolve" vite        # Module resolution
DEBUG="vite:hmr" vite            # HMR events
DEBUG="vite:deps" vite           # Dependency optimization
DEBUG="vite:transform" vite      # Module transforms
DEBUG="vite:legacy" vite         # Legacy plugin (plugin-legacy)
```

#### Development/Testing Environment Variables

| Variable | Purpose |
|----------|---------|
| `DEBUG` | Enable debug logging for specific Vite subsystems |
| `DEBUG_DISABLE_SOURCE_MAP` | Disable source maps during Vite's own build |
| `VITE_TEST_BUILD` | Enable build-mode E2E testing |
| `VITE_DEBUG_SERVE` | Debug serve mode |
| `VITE_PRESERVE_BUILD_ARTIFACTS` | Keep build artifacts after tests for inspection |

---

## 6. Performance

### 6.1 Dev Server Performance

#### Startup Optimization

1. **Dependency pre-bundling** converts many small ESM files into a single bundled file per dependency, eliminating the request waterfall that would occur if, say, `lodash-es` (600+ modules) were served unbundled.

2. **`optimizeDeps.holdUntilCrawlEnd`** (default `true`) delays serving modules until the initial dependency scan completes, preventing mid-session re-optimization that would trigger a full page reload.

3. **Server warmup** pre-transforms critical files so they are ready when the browser requests them.

#### HMR Performance

HMR updates are surgical — only the changed module and its direct importers are re-processed. The module graph enables this by tracking precise dependency relationships.

Key factors affecting HMR speed:
- Module graph depth (deeply nested imports = more traversal)
- Transform plugin count and complexity
- CSS changes are independently hot-replaceable (no JS re-execution needed)

### 6.2 Build Performance

#### Rolldown as Bundler

Vite v8 uses Rolldown (a Rust-based Rollup-compatible bundler) for production builds, providing substantial performance improvements over the esbuild+Rollup combination in earlier Vite versions.

#### Code Splitting Strategy

Automatic code splitting occurs at:
- Dynamic `import()` boundaries
- CSS associated with async chunks
- Shared modules referenced by multiple entry points

Control chunk splitting:

```typescript
export default defineConfig({
  build: {
    rolldownOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          lodash: ['lodash-es'],
        },
        // Or function form
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return 'vendor'
          }
        },
      }
    }
  }
})
```

#### Asset Inlining

Assets smaller than `build.assetsInlineLimit` (default 4KB) are inlined as base64 data URIs to reduce HTTP requests. Custom MIME types are registered for:

| Extension | MIME Type |
|-----------|----------|
| `.ico` | `image/x-icon` |
| `.cur` | `image/x-icon` |
| `.flac` | `audio/flac` |
| `.eot` | `application/vnd.ms-fontobject` |

#### Chunk Size Monitoring

```typescript
export default defineConfig({
  build: {
    chunkSizeWarningLimit: 500,  // KB — warns when chunks exceed this
  }
})
```

### 6.3 CSS Performance

#### CSS Code Splitting

When `build.cssCodeSplit` is `true` (default), CSS is extracted per async chunk and loaded on demand. This prevents loading CSS for routes the user hasn't visited.

#### LightningCSS for Speed

LightningCSS (written in Rust) is significantly faster than PostCSS for CSS transformation and minification:

```typescript
export default defineConfig({
  css: {
    transformer: 'lightningcss',
  },
  build: {
    cssMinify: 'lightningcss',
  }
})
```

### 6.4 Module Runner Performance

The module runner (`vite/module-runner`) is a lightweight, framework-agnostic module execution runtime. It is designed for SSR and worker environments with a small footprint — the build target enforces a **55KB bundle size limit**.

---

## 7. Security

### 7.1 File System Access Control

> [!WARNING]
> The dev server can expose sensitive files if not properly configured. Always verify `server.fs` settings in shared or CI environments.

#### Strict Mode (Default: Enabled)

When `server.fs.strict` is `true`, Vite restricts file serving to the project root and its dependencies. Files outside this boundary receive a 403 response.

```typescript
export default defineConfig({
  server: {
    fs: {
      strict: true,
      
      // Explicitly allow additional directories
      allow: [
        '/path/to/shared-components',
        '../sibling-project/src',
      ],
      
      // Deny patterns (applied even within allowed directories)
      deny: [
        '.env',
        '.env.*',
        '*.{crt,pem}',
        '**/.git/**',
      ],
    }
  }
})
```

The default deny list blocks `.env` files, TLS certificates/keys, and `.git` directories.

### 7.2 Content Security Policy (CSP)

Vite supports CSP via nonce injection in HTML:

```typescript
export default defineConfig({
  html: {
    cspNonce: 'PLACEHOLDER',  // Replaced at runtime by your server
  }
})
```

The plugin-legacy package generates CSP hashes for inline scripts when `cspInlineScripts` is enabled, allowing strict CSP policies without nonces:

```typescript
legacy({
  renderModernChunks: true,
  // CSP hashes are automatically generated for legacy inline scripts
})
```

### 7.3 Source Map Security

Production source maps expose original source code. Control exposure:

```typescript
export default defineConfig({
  build: {
    sourcemap: 'hidden',  // Generates maps but doesn't reference them in output
    // Options: true | false | 'inline' | 'hidden'
  }
})
```

Use `'hidden'` source maps for error monitoring services (Sentry, Datadog) that upload maps separately — the browser never sees them.

### 7.4 Environment Variable Security

The `envPrefix` configuration controls which environment variables leak to client bundles:

```typescript
export default defineConfig({
  envPrefix: ['VITE_', 'PUBLIC_'],  // Only these prefixes are exposed
})
```

> [!CAUTION]
> Setting `envPrefix` to an empty string (`''`) exposes ALL environment variables to client-side code, including `DATABASE_URL`, API keys, and other secrets. Never do this.

### 7.5 Dependency Security

Pre-bundled dependencies are stored in `node_modules/.vite/deps/`. This cache should be:

- Excluded from version control (it is, via standard `.gitignore` for `node_modules`)
- Regenerated in CI environments (`--force` or clean installs)
- Audited via standard `npm audit` / `pnpm audit`

### 7.6 Dev Server Network Exposure

By default, the dev server binds to `localhost` only. Binding to `0.0.0.0` (`--host`) exposes it to the local network:

```bash
# Binds to localhost only (safe)
vite

# Binds to all interfaces (use only on trusted networks)
vite --host
```

The HMR WebSocket connection follows the same host binding. When using `--host`, the HMR overlay displays the server URL, which could leak internal network information.

---

## 8. Developer Internals

### 8.1 Self-Build Pipeline

Vite builds itself using Rolldown. The build configuration in `rolldown.config.ts` produces four distinct outputs:

| Config | Entry | Output | Target |
|--------|-------|--------|--------|
| `envConfig` | `src/client/env.ts` | `dist/client/env.mjs` | Browser (es2020) |
| `clientConfig` | `src/client/client.ts` | `dist/client/client.mjs` | Browser (es2020) |
| `nodeConfig` | `src/node/{index,cli,internal}.ts` | `dist/node/*.js` | Node.js (ESM) |
| `moduleRunnerConfig` | `src/module-runner/index.ts` | `dist/node/module-runner.js` | Node.js (minified) |

**Build plugins used in self-build:**

| Plugin | Purpose |
|--------|---------|
| `shimDepsPlugin` | Patches postcss-load-config and postcss-import for ESM compatibility |
| `buildTimeImportMetaUrlPlugin` | Resolves `import.meta.url` references at build time |
| `licensePlugin` | Collects and emits third-party license file |
| `writeTypesPlugin` | Generates TypeScript declaration files |
| `enableSourceMapsInWatchModePlugin` | Enables source maps only during watch builds |
| `externalizeDepsInWatchPlugin` | Externalizes dependencies in watch mode for faster rebuilds |
| `bundleSizeLimit(55)` | Enforces 55KB limit on the module-runner bundle |

### 8.2 Internal Plugin Pipeline

The 29+ built-in plugins are loaded in a specific order that is critical to correct operation. Understanding this order is essential for plugin authors.

```
Phase 1: Pre-alias
  1.  optimizedDepsPlugin          (dev only — serves pre-bundled deps)
  2.  watchPackageDataPlugin       (watches package.json changes)
  3.  preAliasPlugin               (dev only — resolves optimized deps before alias)
  4.  aliasPlugin                  (path alias resolution)

Phase 2: User pre-plugins
  5.  [user plugins with enforce: 'pre']

Phase 3: Core transforms
  6.  modulePreloadPolyfillPlugin  (polyfill for modulepreload)
  7.  oxcResolvePlugin             (module resolution via oxc)
  8.  htmlInlineProxyPlugin        (proxy for inline HTML scripts)
  9.  cssPlugin                    (CSS processing — largest plugin)
  10. esbuildBannerFooterCompatPlugin
  11. oxcRuntimePlugin             (dev only — oxc transform runtime)
  12. oxcPlugin                    (oxc/esbuild transforms for TS/JSX)
  13. jsonPlugin                   (JSON imports, native)
  14. wasmHelperPlugin             (WASM support)
  15. webWorkerPlugin              (Web Worker bundling)
  16. assetPlugin                  (static asset handling)
  17. forwardConsolePlugin          (console forwarding)

Phase 4: User normal plugins
  18. [user plugins without enforce]

Phase 5: Post-processing
  19. wasmFallbackPlugin           (native WASM fallback)
  20. definePlugin                 (compile-time constants)
  21. cssPostPlugin                (CSS post-processing — extraction, minification)
  22. buildHtmlPlugin              (build only — HTML bundling)
  23. workerImportMetaUrlPlugin    (import.meta.url worker support)
  24. assetImportMetaUrlPlugin     (import.meta.url asset support)

Phase 6: Build pre-plugins
  25. [build pre plugins]

Phase 7: Analysis
  26. dynamicImportVarsPlugin      (dynamic import variable support)
  27. importGlobPlugin             (import.meta.glob)

Phase 8: User post-plugins
  28. [user plugins with enforce: 'post']

Phase 9: Build post + dev-only
  29. [build post plugins]
  30. clientInjectionsPlugin       (dev only — injects client scripts)
  31. cssAnalysisPlugin            (dev only — CSS dependency analysis)
  32. importAnalysisPlugin         (dev only — import rewriting)
```

> [!NOTE]
> The `enforce` property on user plugins determines their position in this pipeline. `'pre'` inserts before core transforms, `'post'` inserts after analysis. Omitting `enforce` places the plugin between core transforms and post-processing.

### 8.3 Plugin API

Vite's plugin API extends Rollup's plugin interface with additional hooks:

#### Vite-Specific Hooks

| Hook | When | Purpose |
|------|------|---------|
| `config(config, env)` | Config resolution | Modify or extend config |
| `configResolved(config)` | After config resolution | Read final config |
| `configureServer(server)` | Server creation | Add custom middleware |
| `configurePreviewServer(server)` | Preview server creation | Add preview middleware |
| `transformIndexHtml(html, ctx)` | HTML processing | Transform HTML |
| `handleHotUpdate(ctx)` | HMR event | Custom HMR handling |
| `hotUpdate(ctx)` | HMR event (new API) | Per-environment HMR |

#### Plugin Ordering

```typescript
const myPlugin = {
  name: 'my-plugin',
  enforce: 'pre',     // 'pre' | 'post' | undefined
  apply: 'serve',     // 'serve' | 'build' | undefined | function
}
```

#### Object Hook Format (Performance Optimization)

```typescript
const myPlugin = {
  name: 'my-plugin',
  transform: {
    filter: {
      id: /\.(ts|tsx)$/,  // Only process matching files
    },
    handler(code, id) {
      // Transform logic
    },
    order: 'pre',  // Hook execution order
  },
}
```

The `filter` property enables Vite to skip calling the hook for non-matching modules, providing significant performance improvement in large projects.

### 8.4 Module Graph

The dev server maintains a module graph (`server.moduleGraph`) that tracks:

- Module URL → file path mapping
- Import/export relationships
- Transform results (cached)
- HMR boundaries and acceptors
- Self-accepting modules (handle their own updates)

Each environment has its own module graph instance, enabling independent module tracking for client, SSR, and custom environments.

Key module graph operations:

```typescript
// Get module by URL
const mod = server.moduleGraph.getModuleByUrl('/src/main.ts')

// Invalidate module (triggers re-transform)
server.moduleGraph.invalidateModule(mod)

// Iterate all modules
for (const mod of server.moduleGraph.idToModuleMap.values()) {
  console.log(mod.url, mod.importedModules.size)
}
```

### 8.5 HMR Protocol

The HMR system communicates between server and client via WebSocket:

**Server → Client messages:**
- `update` — module update with list of changed modules and timestamps
- `full-reload` — trigger full page reload (when HMR boundary is not found)
- `prune` — remove stale modules
- `error` — display error overlay
- `custom` — custom events for plugin communication

**Client → Server messages:**
- `connected` — client connected
- `custom` — custom events

The client-side HMR runtime (`dist/client/client.mjs`) handles:
- WebSocket connection management with auto-reconnect
- Module update application via `import.meta.hot.accept()`
- CSS hot replacement (swap `<link>` tags without JS re-execution)
- Error overlay rendering and dismissal
- Custom event dispatch

### 8.6 Type System

Vite ships extensive type declarations:

**`client.d.ts`** — Ambient declarations for module types in application code:

| Pattern | Type | Description |
|---------|------|-------------|
| `*.module.css/scss/sass/less/styl/stylus/pcss/sss` | CSS Modules | `Record<string, string>` |
| `*.css` | Plain CSS | `string` |
| `*.png/jpg/jpeg/gif/svg/ico/webp/avif/jxl/...` | Images | `string` (URL) |
| `*.mp4/webm/ogg/mp3/wav/flac/aac/opus/...` | Media | `string` (URL) |
| `*.woff/woff2/ttf/otf` | Fonts | `string` (URL) |
| `*.wasm?init` | WASM | Init function |
| `*?worker` | Web Worker | Worker constructor |
| `*?sharedworker` | Shared Worker | SharedWorker constructor |
| `*?raw` | Raw | `string` (file contents) |
| `*?url` | URL | `string` (resolved URL) |
| `*?inline` | Inline | `string` (inlined content) |

**`importMeta.d.ts`** — Augments `ImportMeta` with `env`, `hot`, and `glob` types.

### 8.7 Code Conventions

The Vite codebase enforces these conventions:

| Convention | Enforcement |
|------------|------------|
| ESM-only (`"type": "module"`) | Package config |
| Consistent type imports | `@typescript-eslint/consistent-type-imports` |
| No `require()` in packages | ESLint rule |
| No `__dirname`/`__filename` | ESLint rule — use `import.meta.dirname` |
| Node protocol required | `node:fs` not `fs` |
| Semicolons off, single quotes | oxfmt |
| Pre-commit lint | `pnpm exec lint-staged --concurrent false` via `simple-git-hooks` |

### 8.8 Testing Infrastructure

#### Test Categories

```bash
# Unit tests (fast, no browser)
pnpm test-unit

# E2E tests — dev server mode
pnpm test-serve

# E2E tests — build mode
VITE_TEST_BUILD=1 pnpm test-build

# All tests
pnpm test
```

#### E2E Test Architecture

E2E tests use a **playground pattern**: each directory under `playground/` is a self-contained Vite project that serves as a test fixture.

```
playground/
├── css/                  # CSS feature tests
├── html/                 # HTML processing tests
├── worker/               # Web Worker tests
├── ssr-*                 # SSR feature tests
└── ...                   # ~50+ test apps
```

Tests use Playwright (Chromium) to interact with the running dev server or built output, asserting on DOM state, network requests, and console output.

#### Test Configuration

- Unit tests: Default Vitest config
- E2E tests: `vitest.config.e2e.ts`
- Serve vs build mode: Controlled by `VITE_TEST_BUILD` env var
- Artifact preservation: `VITE_PRESERVE_BUILD_ARTIFACTS=1`

#### Monorepo Scripts

| Script | Purpose |
|--------|---------|
| `pnpm build` | Build all packages |
| `pnpm dev` | Dev mode (watch) for all packages |
| `pnpm test` | Run all tests (unit + serve + build) |
| `pnpm test-unit` | Unit tests only |
| `pnpm test-serve` | E2E serve tests |
| `pnpm test-build` | E2E build tests |
| `pnpm lint` | ESLint |
| `pnpm format` | oxfmt formatting |
| `pnpm typecheck` | TypeScript type checking |
| `pnpm docs` | VitePress dev server for docs |
| `pnpm docs-build` | Build documentation site |
| `pnpm docs-serve` | Preview built docs |
| `pnpm release` | Release workflow |
| `pnpm ci-publish` | CI publish workflow |

---

## 9. Integration Points

### 9.1 Framework Integrations

Vite is designed as a framework-agnostic build tool with official and community plugins for major frameworks:

| Framework | Plugin | Capabilities |
|-----------|--------|-------------|
| Vue | `@vitejs/plugin-vue` | SFC compilation, HMR, SSR |
| React | `@vitejs/plugin-react` | JSX transform (Babel), Fast Refresh |
| React (SWC) | `@vitejs/plugin-react-swc` | JSX transform (SWC), Fast Refresh |
| Svelte | `@sveltejs/vite-plugin-svelte` | Svelte compilation, HMR |
| Solid | `vite-plugin-solid` | Solid JSX, HMR |
| Preact | `@preact/preset-vite` | Preact JSX, prefresh HMR |

### 9.2 Backend Integration

For non-SPA architectures (Rails, Laravel, Django, etc.), Vite provides a manifest-based integration:

1. Enable `build.manifest: true` in config
2. In development, include `<script type="module" src="http://localhost:5173/@vite/client">` and your entry point
3. In production, read `.vite/manifest.json` to resolve hashed file names

The manifest JSON structure:

```json
{
  "src/main.ts": {
    "file": "assets/main-abc123.js",
    "src": "src/main.ts",
    "isEntry": true,
    "css": ["assets/main-def456.css"],
    "imports": ["_vendor-ghi789.js"]
  }
}
```

### 9.3 Rolldown/Rollup Plugin Compatibility

Vite's plugin interface is Rollup-compatible with extensions. Most Rollup plugins work in Vite with these caveats:

- Rollup plugins that use `this.emitFile` work in build mode only
- Plugins expecting Rollup-specific internal APIs may need adaptation
- The `enforce` and `apply` properties are Vite-specific extensions
- Object hook format with `filter` is a Vite/Rolldown extension

> [!TIP]
> When a Rollup plugin doesn't work in dev mode, wrap it with `apply: 'build'` to limit it to production builds, and implement a Vite-native equivalent for dev.

### 9.4 create-vite Scaffolding

The `create-vite` package provides 20+ project templates:

```bash
# Interactive mode
npm create vite@latest

# Direct template selection
npm create vite@latest my-app -- --template react-ts
```

Available template families: `vanilla`, `vue`, `react`, `preact`, `lit`, `svelte`, `solid`, `qwik` — each with TypeScript variants.

Templates are stored in `packages/create-vite/template-*/` and copied to the target directory with package name and dependency version substitution.

### 9.5 Programmatic API

The full programmatic API exported from `vite`:

```typescript
import {
  // Server
  createServer,
  preview,
  
  // Build
  build,
  
  // Config
  defineConfig,
  loadConfigFromFile,
  resolveConfig,
  
  // Environment
  createNodeDevEnvironment,
  
  // Plugins
  createFilter,
  
  // Module runner
  ModuleRunner,        // from 'vite/module-runner'
  
  // Utilities
  normalizePath,
  searchForWorkspaceRoot,
  send,
  transformWithEsbuild,
  preprocessCSS,
  
  // Types (re-exported)
  type Plugin,
  type UserConfig,
  type ResolvedConfig,
  type ViteDevServer,
  type HmrContext,
  // ... extensive type exports
} from 'vite'
```

### 9.6 Known Community Issues

Current open issues that administrators should be aware of:

| Issue | Description | Impact |
|-------|-------------|--------|
| #22239 | Same module executed twice with different URL queries | Potential state duplication |
| #22022 | Runtime exception importing conditional CJS module | CJS interop edge case |
| #22225 | plugin-legacy fails with esbuild 0.27.7+ | Legacy browser builds may fail |
| #21395 | Hidden errors from plugins | Silent failures in plugin pipeline |
| #21911 | CSS minifier blocks progressive modern CSS | Modern CSS features may be stripped |
| #22176 | CJS interop factory shadowed re-bundling | Rolldown CJS handling regression |
| #22234 | Oxc minifier removes if guard | Minification correctness bug |
| #22251 | HMR stops with TS circular dependency | Dev experience degradation |
| #21903 | CSS cascade order differs dev vs production | Visual inconsistencies between modes |

> [!WARNING]
> Issue #21903 (CSS cascade order differences between dev and production) is particularly impactful. Always verify CSS-heavy pages in both modes. The root cause is that dev mode serves CSS as individual `<style>` tags in import order, while production mode extracts and concatenates CSS, which can change cascade specificity.

### 9.7 Troubleshooting Reference

#### Dependency Pre-Bundling Failures

| Error | Cause | Solution | Prevention |
|-------|-------|----------|------------|
| `Failed to resolve dependency` | Package not found or misconfigured exports | Check `node_modules` installation and package `exports` field | Use lockfile, `pnpm install --frozen-lockfile` |
| `Outdated pre-bundle deps` | Cache mismatch after dependency update | Delete `node_modules/.vite` or use `--force` | Always restart dev server after `pnpm install` |
| `CJS interop error` | CommonJS module with complex export pattern | Add to `optimizeDeps.needsInterop` | Document known CJS interop requirements |

#### Build Failures

| Error | Cause | Solution | Prevention |
|-------|-------|----------|------------|
| `Chunk exceeds size limit` | Large vendor bundles | Configure `manualChunks` to split vendors | Set `chunkSizeWarningLimit` appropriately |
| `Missing export` | Tree-shaking removed needed export | Mark as side-effect in `package.json` `sideEffects` | Verify side-effect declarations |
| `CSS order mismatch` | Import order differs between dev and build | Ensure deterministic CSS import ordering | Test production builds regularly |

#### Dev Server Issues

| Error | Cause | Solution | Prevention |
|-------|-------|----------|------------|
| `EADDRINUSE` | Port already in use | Use `--port` flag or kill existing process | Set `server.strictPort: false` (default) |
| `403 Restricted` | File outside `server.fs.allow` | Add directory to `server.fs.allow` | Configure allow list in shared config |
| `HMR connection lost` | WebSocket disconnected | Check proxy/firewall WebSocket pass-through | Configure `server.hmr.host/port` explicitly |
| `Full page reload` (unexpected) | No HMR boundary found for module | Add `import.meta.hot.accept()` in boundary module | Ensure framework plugin provides HMR boundaries |

---

_Generated May 2026 from vitejs/vite at 66f3194. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
