Communitygithub.com

Vite 模式

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

Vite 模式 是什麼?

此技能為 Vite 8+ 專案提供全面的建置工具與開發伺服器模式,涵蓋設定檔配置、環境變數管理、開發伺服器代理設定、函式庫模式、依賴預建置,以及常見的生產環境陷阱。它詳細說明 Vite 的雙模式運作方式:開發模式將原始檔案以原生 ESM 形式提供服務,實現快速冷啟動與精確 HMR;建置模式則使用 Rolldown (v7+) 或 Rollup (v5-v6) 進行生產環境打包。技能特別強調安全邊界的重要性,清楚指出 `VITE_` 前綴並非安全邊界,任何以此前綴開頭的變數都會在客戶端套件中靜態內聯,因此絕不能用於存放 API 金鑰等機密資訊。此外,它還提供了避免 barrel 檔案、明確指定匯入副檔名、以及預熱熱門路徑等效能最佳化建議,協助開發者維持 Vite 專案的快速開發體驗。此模式支援所有使用 Vite 作為建置工具的專案,包括但不限於 React、Vue 及 TypeScript 應用程式。

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

在你喜歡的 AI 中提問

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

說明文件

Vite 模式 是做什麼的?

適用於 Vite 8+ 專案的建置工具與開發伺服器模式。涵蓋設定檔配置、環境變數、代理設定、函式庫模式、依賴預建置,以及常見的生產環境陷阱。

使用時機

  • 配置 vite.config.ts 或 vite.config.js
  • 設定環境變數或 .env 檔案
  • 為 API 後端配置開發伺服器代理
  • 最佳化建置輸出(區塊、最小化、靜態資源)
  • 使用 build.lib 發布函式庫
  • 疑難排解依賴預建置或 CJS/ESM 互通性問題
  • 除錯 HMR、開發伺服器或建置錯誤
  • 選擇或排序 Vite 外掛程式

運作原理

  • 開發模式將原始檔案以原生 ESM 形式提供服務——無需打包。轉換按需求針對每個模組請求進行,這就是為什麼冷啟動快速且 HMR 精確。
  • 建置模式使用 Rolldown (v7+) 或 Rollup (v5–v6) 為生產環境打包應用程式,並進行樹狀搖晃、程式碼分割,以及基於 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 檔案會被 git 忽略,用於存放本機機密。

客戶端存取

只有 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             // 布林值

在設定檔中使用 Env

// 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 編碼和停用原始碼映射都無法隱藏它。一個確定的攻擊者可以從已發布的 JavaScript 中提取任何 VITE_ 變數。

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

loadEnv('') 陷阱

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

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

生產環境中的原始碼映射

生產環境中的原始碼映射會洩露你的原始程式碼。除非你將其上傳到錯誤追蹤工具(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。

建置最佳化

手動區塊

// 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 進行驗證。

部署後區塊過時

新的建置會產生新的區塊雜湊。活躍的工作階段會請求已不存在的舊檔案名稱。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() 在……

…[為翻譯而截斷]

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.

相關技能