Communitygithub.com

vite-patterns

Vite 建置工具模式,包含設定、外掛、HMR、環境變數、代理設定、SSR、程式庫模式、相依性預先打包與建置最佳化。當處理 vite.config.ts、Vite 外掛或基於 Vite 的專案時啟用。

vite-patterns 是什麼?

這個技能提供 Vite 建置工具與開發伺服器的完整模式參考,適用於 Vite 第 8 版以上專案。內容涵蓋設定結構、環境變數處理、開發伺服器代理設定、程式庫模式、相依性預先打包,以及常見的生產環境陷阱與反模式。它詳細說明 Vite 的開發模式(以原生 ESM 按需轉換)與建置模式(使用 Rolldown 或 Rollup 進行綑綁)的運作原理,並深入解釋外掛的共用介面、HMR API 的手動使用時機與安全實務(如 VITE_ 前綴的靜態內嵌特性與 source map 管控)。此技能支援所有整合 Vite 的專案與框架(React、Vue、SvelteKit 等),並提供可複製貼上的程式碼範例與最佳實務,幫助開發者避免效能瓶頸(如 barrel file 與隱含副檔名)與安全漏洞。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/vite-patterns

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Vite 模式

Vite 第 8 版以上專案的建置工具與開發伺服器模式。涵蓋設定、環境變數、代理設定、程式庫模式、相依性預先打包,以及常見的生產環境陷阱。

使用時機

  • 設定 vite.config.ts 或 vite.config.js
  • 設定環境變數或 .env 檔案
  • 設定開發伺服器代理以連接 API 後端
  • 最佳化建置輸出(chunk、最小化、資源)
  • 使用 build.lib 發行程式庫
  • 疑難排解相依性預先打包或 CJS/ESM 互操作
  • 除錯 HMR、開發伺服器或建置錯誤
  • 選擇或排序 Vite 外掛

運作原理

  • 開發模式將原始檔案視為原生 ESM 提供服務——無需綑綁。轉換針對每個模組請求按需進行,因此冷啟動快速,HMR 精確。
  • 建置模式使用 Rolldown(第 7 版以上)或 Rollup(第 5–6 版)將應用程式綑綁以用於生產環境,並進行搖樹最佳化、程式碼分割與基於 Oxc 的最小化。
  • 相依性預先打包透過 esbuild 將 CJS/UMD 相依性轉換為 ESM 一次,並將結果快取於 node_modules/.vite,後續啟動可跳過此步驟。
  • 外掛在開發與建置過程中共用統一的介面——同一個外掛物件適用於開發伺服器的按需轉換以及生產管線。
  • 環境變數在建置時靜態內嵌。VITE_ 前綴的變數成為綑綁結果中的公開常數;未前綴的任何內容對客戶端程式碼不可見。

範例

設定結構

基本設定

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

條件式設定

// 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())   // 僅 VITE_ 前綴(安全)

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

關鍵設定選項

鍵預設值說明
root'.'專案根目錄(index.html 所在位置)
base'/'已部署資源的公開基礎路徑
envPrefix'VITE_'客戶端暴露的環境變數前綴
build.outDir'dist'輸出目錄
build.minify'oxc'最小化工具('oxc'、'terser' 或 false)
build.sourcemapfalsetrue、'inline' 或 'hidden'

外掛

必備外掛

大多數外掛需求可由少數幾個維護良好的套件滿足。在自行編寫前,請優先使用這些。

外掛用途使用時機
@vitejs/plugin-react-swc透過 SWC 的 React HMR + Fast RefreshReact 應用程式的預設(比 Babel 變體更快)
@vitejs/plugin-react透過 Babel 的 React HMR + Fast Refresh僅當你需要 Babel 外掛(emotion、MobX 裝飾器)時
@vitejs/plugin-vueVue 3 SFC 支援Vue 應用程式
vite-plugin-checker在工作執行緒中執行 tsc + ESLint,搭配 HMR 覆蓋層任何 TypeScript 應用程式——Vite 在 vite build 期間不會進行型別檢查
vite-tsconfig-paths遵循 tsconfig.json 的 paths 別名當你已在 tsconfig.json 中設定別名時
vite-plugin-dts在程式庫模式下發出 .d.ts 檔案發行 TypeScript 程式庫
vite-plugin-svgr將 SVG 導入為 React 元件使用 SVG 作為元件的 React 應用程式
rollup-plugin-visualizer綑綁結果的樹狀圖/旭日圖報告定期綑綁大小審計(使用 enforce: 'post')
vite-plugin-pwa零設定的 PWA + Workbox離線可用的應用程式

重要提醒: vite build 會轉譯但不會進行型別檢查。除非你新增 vite-plugin-checker 或在 CI 中執行 tsc --noEmit,否則型別錯誤會靜默地發佈到生產環境。

自行編寫自訂外掛

自行編寫的情況很少見——大多數需求可由現有外掛滿足。當你真的需要時,請先在 vite.config.ts 中內嵌編寫,僅在重複使用時才提取出來。

// vite.config.ts — 最小化內嵌外掛
function myPlugin(): Plugin {
  return {
    name: 'my-plugin',                       // 必要,必須唯一
    enforce: 'pre',                           // 'pre' | 'post'(選用)
    apply: 'build',                           // 'build' | 'serve'(選用)
    transform(code, id) {
      if (!id.endsWith('.custom')) return
      return { code: transformCustom(code), map: null }
    },
  }
}

關鍵鉤子: transform(修改原始碼)、resolveId + load(虛擬模組)、transformIndexHtml(注入到 HTML)、configureServer(新增開發中介軟體)、hotUpdate(自訂 HMR——在 v7+ 中取代已棄用的 handleHotUpdate)。

虛擬模組使用 \0 前綴慣例——resolveId 回傳 '\0virtual:my-id' 以讓其他外掛跳過。使用者程式碼導入 'virtual:my-id'。

有關完整的外掛 API,請參閱 vite.dev/guide/api-plugin。在開發期間使用 vite-plugin-inspect 來除錯轉換管線。

HMR API

框架外掛(@vitejs/plugin-react、@vitejs/plugin-vue 等)會自動處理 HMR。僅在建立自訂狀態儲存、開發工具或與框架無關且需要在更新間保持狀態的公用程式時,才直接使用 import.meta.hot。

// src/store.ts — 手動 HMR,適用於一般模組
if (import.meta.hot) {
  // 在更新間保持狀態(必須**變異**,絕不能重新指派 .data)
  import.meta.hot.data.count = import.meta.hot.data.count ?? 0

  // 在模組被取代前清理副作用
  import.meta.hot.dispose((data) => clearInterval(data.intervalId))

  // 接受此模組自身的更新
  import.meta.hot.accept()
}

所有 import.meta.hot 程式碼都會在生產建置中被搖樹移除——無需額外移除保護。

環境變數

Vite 會按順序載入 .env、.env.local、.env.[mode]、.env.[mode].local(後者覆蓋前者);*.local 檔案會被 .gitignore 忽略,用於存放本機機密。

客戶端存取

只有 VITE_ 前綴的變數會暴露給客戶端程式碼:

import.meta.env.VITE_API_URL   // 字串
import.meta.env.MODE            // 'development' | 'production' | 自訂
import.meta.env.BASE_URL        // base 設定值
import.meta.env.DEV             // 布林值
import.meta.env.PROD            // 布林值
import.meta.env.SSR             // 布林值

在設定中使用環境變數

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

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd())          // 僅 VITE_ 前綴(安全)
  return {
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  }
})

安全性

VITE_ 前綴不是安全邊界

任何帶有 VITE_ 前綴的變數都會在建置時靜態內嵌到客戶端綑綁結果中。最小化、Base64 編碼或停用 source map 都無法隱藏它。有決心的攻擊者可以從已傳送的 JavaScript 中提取任何 VITE_ 變數。

規則: 僅將公開值(API 網址、功能旗標、公開金鑰)放入 VITE_ 變數中。機密(API 金鑰、資料庫網址、私密金鑰)必須存在於伺服器端,透過 API 或無伺服器函數提供服務。

loadEnv('') 陷阱

// 錯誤:將 '' 作為第三個參數傳遞會載入**所有**環境變數——包括伺服器機密——
// 並使其可透過 `define` 內嵌到客戶端程式碼中。
const env = loadEnv(mode, process.cwd(), '')

// 正確:明確的前綴列表
const env = loadEnv(mode, process.cwd(), ['VITE_', 'APP_'])

生產環境的 Source Map

生產環境的 source map 會泄漏你的原始原始碼。請停用它們,除非你上傳到錯誤追蹤服務(Sentry、Bugsnag)並在之後於本機刪除:

build: {
  sourcemap: false,                                  // 預設值——請保持此設定
}

.gitignore 檢查清單

  • .env.local、.env.*.local — 本機機密覆蓋
  • dist/ — 建置輸出
  • node_modules/.vite — 預先打包快取(過時項目會導致幽靈錯誤)

伺服器代理

// vite.config.ts — server.proxy
server: {
  proxy: {
    '/foo': 'http://localhost:4567',                    // 字串簡寫

    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,                               // 虛擬主機後端需要此設定
      rewrite: (path) => path.replace(/^\/api/, ''),
    },
  },
}

若要代理 WebSocket,請在路由設定中新增 ws: true。

建置最佳化

手動 Chunk

// vite.config.ts — build.rolldownOptions
build: {
  rolldownOptions: {
    output: {
      // 物件形式:分組特定套件
      manualChunks: {
        'react-vendor': ['react', 'react-dom'],
        'ui-vendor': ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
      },
    },
  },
}
// 函數形式:根據啟發式分割
manualChunks(id) {
  if (id.includes('node_modules/react')) return 'react-vendor'
  if (id.includes('node_modules')) return 'vendor'
}

效能

避免 Barrel 檔案

Barrel 檔案(重新導出目錄中所有內容的 index.ts)會迫使 Vite 載入每個重新導出的檔案,即使你只導入單一符號。這是官方文件指出的頭號開發伺服器效能瓶頸。

// 錯誤——導入一個工具函數會迫使 Vite 載入整個 barrel
import { slash } from '@/utils'

// 正確——直接導入,只載入一個檔案
import { slash } from '@/utils/slash'

明確指定導入副檔名

每個隱含副檔名會透過 resolve.extensions 強制進行最多 6 次檔案系統檢查。在大型程式碼庫中,這會累積起來。

// 錯誤
import Component from './Component'

// 正確
import Component from './Component.tsx'

請將 tsconfig.json 的 allowImportingTsExtensions 與 resolve.extensions 縮小到僅包含你實際使用的副檔名。

預熱熱門路徑

server.warmup.clientFiles 會在瀏覽器請求之前預先轉換已知的熱門進入點——消除大型應用程式的冷載入請求瀑布。

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

分析慢速開發伺服器

當 vite dev 感覺緩慢時,先執行 vite --profile,與應用程式互動,然後按下 p+enter 儲存 .cpuprofile。在 Speedscope 中載入,找出哪些外掛耗費時間——通常是社群外掛中的 buildStart、config 或 configResolved 鉤子。

程式庫模式

發行 npm 套件時,請使用 build.lib。有兩個陷阱比設定細節更重要:

  1. 型別不會被發出——請新增 vite-plugin-dts 或單獨執行 tsc --emitDeclarationOnly。
  2. 對等相依性必須外部化——未列出的對等相依性會被綑綁到你的程式庫中,導致消費端發生重複執行時期錯誤。
// 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'],  // 每個對等相依性
  },
}

SSR 外部化

單純的 createServer({ middlewareMode: true }) 設定是框架作者的地盤。大多數應用程式應使用 Nuxt、Remix、SvelteKit、Astro 或 TanStack Start。作為框架使用者,你可能需要調整的是當相依性在 SSR 中中斷時的外部化設定:

// vite.config.ts — ssr 選項
ssr: {
  external: ['node-native-package'],           // 在 SSR 綑綁結果中保留為 require()
  noExternal: ['esm-only-package'],            // 強制綑綁到 SSR 輸出(修復大多數 SSR 錯誤)
  target: 'node',                              // 'node' 或 'webworker'
}

相依性預先打包

Vite 會預先打包相依性,以將 CJS/UMD 轉換為 ESM 並減少請求數量。

// vite.config.ts — optimizeDeps
optimizeDeps: {
  include: [
    'lodash-es',                              // 強制預先打包已知的沉重相依性
    'cjs-package',                            // 導致互操作問題的 CJS 相依性
    'deep-lib/components/**',                 // 深層導入的 glob 模式
  ],
  exclude: ['local-esm-package'],             // 如果排除,則必須是有效的 ESM
  force: true,                                // 忽略快取,重新最佳化(臨時除錯用)
}

常見陷阱

開發環境與建置環境不一致

開發環境使用 esbuild/Rolldown 進行轉換;建置環境使用 Rolldown 進行綑綁。CJS 程式庫在兩者之間可能表現不同。在部署前,務必使用 vite build && vite preview 進行驗證。

部署後的過期 Chunk

新的建置會產生新的 chunk 雜湊。具有活躍工作階段的使用者會請求不再存在的舊檔案名稱。Vite 沒有內建的解決方案。緩解措施:

  • 在部署時間窗口內保留舊的 dist/assets/ 檔案
  • 在路由器中捕獲動態導入錯誤,並強制重新載入頁面

Docker 與容器

Vite 預設繫結到 localhost,這從容器外部無法訪問:

// vite.config.ts — Docker/容器設定
server: {
  host: true,                                  // 繫結 0.0.0.0
  hmr: { clientPort: 3000 },                   // 如果在反向代理後方
}

單一儲存庫檔案存取

Vite 將檔案提供限制在專案根目錄。根目錄外的套件會被封鎖:

// vite.config.ts — 單一儲存庫檔案存取
server: {
  fs: {
    allow: ['..'],                             // 允許父目錄(工作區根目錄)
  },
}

反模式

// 錯誤:將 envPrefix 設為 '' 會將所有環境變數(包括機密)暴露給客戶端
envPrefix: ''

// 錯誤:假設 require() 在 Vite 前端模組中能正常運作(會導致執行時期錯誤)
const fs = require('fs')

// 錯誤:在依賴可能已變更後,未清除 node_modules/.vite 快取就重新啟動
// 請刪除 node_modules/.vite 或使用 optimizeDeps.force: true

// 錯誤:在生產建置中啟用 source map,但未上傳到錯誤追蹤服務
build: {
  sourcemap: true
}

資源

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.

相關技能