Vite 是什麼
Vite 是一個以 ES Modules 為基礎、具熱更新 (HMR) 的前端開發工具。開發階段直接讓瀏覽器載入原始碼,不需要預先打包。發佈階段再透過 Rollup 或 Rolldown 打包成靜態檔案。
Vite 指令與執行模式
1. 常用指令
| 指令 | 
功能 | 
預設模式 (mode) | 
npm run dev 或 vite | 
啟動開發伺服器,支援即時熱更新 (HMR) | 
development | 
npm run build 或 vite build | 
打包專案成靜態檔案 | 
production | 
npm run preview 或 vite preview | 
啟動一個本地伺服器預覽打包結果 | 
production | 
2. npm run dev vs npm run preview
| 項目 | 
npm run dev | 
npm run preview | 
| 功能 | 
啟動開發伺服器 (Vite Dev Server) | 
啟動預覽伺服器 | 
| 模式 | 
development | 
production | 
| 資源載入 | 
即時讀取原始碼 (src/main.ts) | 
載入打包後的靜態檔 (dist/) | 
| 是否需先打包 | 
不需要 | 
需要先執行 npm run build | 
| 用途 | 
開發、即時更新 (Hot Module Replacement, HMR) | 
模擬正式部署 | 
Vite 設定檔 vite.config.ts 基本結構
範例
1 2 3 4 5 6 7
   | export default defineConfig({   plugins: [react()],   server: {     port: 3000,     open: true   } })
  | 
 
說明
defineConfig():Vite 官方提供的函式,提供型別提示與確保匯出的物件符合 Vite 設定格式。 
plugins:Vite 本身只是一個通用的建構工具,並不「內建」React、Vue、Svelte 等框架支援。設定插件,例如 React,讓 Vite 知道要:
- 如何編譯 
.jsx 或 .tsx 檔案。 
- 如何處理 React HMR (Hot Module Replacement)。
 
- 如何解析 JSX 語法。
 
 
server.port:指定本地伺服器埠號。 
server.open:啟動時自動開啟瀏覽器。 
根據模式 mode 載入 .env 檔
範例
1 2 3 4 5 6 7 8 9 10 11
   | export default defineConfig(({ mode }) => {   const env = loadEnv(mode, process.cwd(), 'VITE')   const port = parseInt(env.VITE_PORT ?? '5173', 10)
    return {     plugins: [react()],     server: {       port     }   } })
  | 
 
mode:決定要載入哪一組 .env.<mode> 檔。 
process.cwd():回傳專案根目錄路徑。 
'VITE':只載入以 VITE_ 開頭的變數。 
parseInt(..., 10):將字串轉為整數 (10 表十進位)。若 .env 中沒有 VITE_PORT,parseInt(..., 10) 結果為 NaN,所以常加預設值。 
mode 是什麼?從哪裡來?
當你執行 Vite 指令時,CLI 會呼叫一個 resolveConfig() 函式,在 resolveConfig() 裡面,Vite 會建立這個「上下文物件」,大致長這樣:
1 2 3 4 5 6 7
   | {   command: 'serve',          mode: 'development',       isSsrBuild: false,         isPreview: false,          ssrBuild: false }
  | 
 
再將這個物件,傳進你的設定函式裡:
1 2 3 4
   | export default defineConfig(({ command, mode }) => {   console.log(command)    console.log(mode)     })
  | 
 
指令對應到的 mode 類別
| 指令 | 
預設 mode | 
vite / vite dev | 
development | 
vite build | 
production | 
vite preview | 
production | 
可以透過 --mode 覆寫,此時 mode 會變成 'staging',並讀取 .env.staging:
1
   | vite build --mode staging
   | 
 
.env 檔載入順序
Vite 根據 mode 依序載入 (後者會覆蓋前者):
.env 
.env.local 
.env.[mode] 
.env.[mode].local 
例:mode = 'development' 時載入順序:
1
   | .env → .env.local → .env.development → .env.development.local
   | 
 
若該檔案不存在,接跳過載入該檔案,並繼續下一個檔案。.env 一直存在且一直都被載入。
process.cwd() 與 __dirname 差別
| 名稱 | 
回傳 | 
用途 | 
process.cwd() | 
當前執行 Vite 指令的資料夾 | 
要根據專案根目錄找資源時 (Vite 常用) | 
__dirname | 
當前檔案所在的資料夾 | 
要根據檔案位置操作檔案時 | 
Vite 使用 process.cwd(),是為了保證即使設定檔在子資料夾,也能找到專案根目錄。
tsconfigPaths() 插件
1 2 3 4 5
   | import tsconfigPaths from 'vite-tsconfig-paths'
  export default defineConfig({   plugins: [react(), tsconfigPaths()] })
   | 
 
功能
自動讀取 tsconfig.json 裡的 paths 設定,讓 Vite 能識別 TypeScript 別名,例如:
1 2 3
   | "paths": {   "@components/*": ["src/components/*"] }
  | 
 
若不使用插件
需手動設定 resolve.alias:
1 2 3 4 5 6 7 8
   | export default defineConfig({   plugins: [react(), tsconfigPaths()],   resolve: {     alias: {       '@components': path.resolve(__dirname, 'src/components')     }   } })
  | 
 
base 與打包後資源路徑
base 用來控制 打包後資源路徑在 HTML 中的 URL 前綴。
開發與打包階段的 index.html
開發時專案目錄下的 index.html:
1 2 3 4
   | <body>     <div id="root"></div>     <script type="module" src="/src/main.tsx"></script> </body>
   | 
 
打包後結構:
1 2 3 4 5 6
   | project/ ├─ dist/ │  ├─ assets/ │  │  ├─ index-COcDBgFa.css │  │  └─ index-DLt9nNv6.js │  └─ index.html
   | 
 
base: '/',打包後的 index.html:
1 2 3 4 5 6 7 8
   | <head>     <title>first-vite</title>     <script type="module" crossorigin src="/assets/index-DLt9nNv6.js"></script>     <link rel="stylesheet" crossorigin href="/assets/index-COcDBgFa.css"> </head> <body>     <div id="root"></div> </body>
   | 
 
base: '/myapp/',打包後的 index.html:
1 2 3 4 5 6 7 8
   | <head>     <title>first-vite</title>     <script type="module" crossorigin src="/myapp/assets/index-DLt9nNv6.js"></script>     <link rel="stylesheet" crossorigin href="/myapp/assets/index-COcDBgFa.css"> </head> <body>     <div id="root"></div> </body>
   | 
 
用來部屬在伺服器的子資料夾 myapp/ 裡面 (例如 GitHub Pages 或 Nginx 子站),需要將整個 dist/ 的內容放入該子資料夾中:
1 2 3 4 5 6
   | (伺服器根目錄) └── myapp/     ├── assets/     │   ├── index-COcDBgFa.css     │   └── DLt9nNv6.js     └─ index.html
   | 
 
base: '',打包後的 index.html:
1 2 3 4 5 6 7 8
   | <head>     <title>first-vite</title>     <script type="module" crossorigin src="assets/index-DLt9nNv6.js"></script>     <link rel="stylesheet" crossorigin href="assets/index-COcDBgFa.css"> </head> <body>     <div id="root"></div> </body>
   | 
 
1 2 3 4 5 6 7 8
   | <head>     <title>first-vite</title>     <script type="module" crossorigin src="https://cdn.example.com/assets/index-DLt9nNv6.js"></script>     <link rel="stylesheet" crossorigin href="https://cdn.example.com/assets/index-COcDBgFa.css"> </head> <body>     <div id="root"></div> </body>
   | 
 
總結
| base | 
打包後資源路徑 | 
用途 | 
'/' | 
/assets/... | 
部署在根目錄。絕對路徑,從網站根目錄載入。 | 
'/myapp/' | 
/myapp/assets/... | 
部署在子資料夾。絕對路徑,從子目錄載入。 | 
'' | 
assets/... | 
相對路徑,根據 HTML 位置載入 | 
'https://cdn.example.com/' | 
https://cdn.example.com/assets/... | 
CDN 載入 | 
注意
若設定:
1 2
   | base: 'https://cdn.example.com/assets/', build: { assetsDir: 'assets' }
   | 
 
打包結果會變成:
1
   | https://cdn.example.com/assets/assets/...
   | 
 
正確寫法:
1 2 3 4 5 6
   |  base: 'https://cdn.example.com/'
 
  base: 'https://cdn.example.com/assets/', build: { assetsDir: '' }
 
  | 
 
完整設定範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | export default defineConfig(({ mode }) => {   const env = loadEnv(mode, process.cwd(), 'VITE')   const port = parseInt(env.VITE_PORT, 10)
    return {     plugins: [react(), tsconfigPaths()],     base: '',     server: {       port: !Number.isNaN(port) ? port : 5001,     },     test: {       environment: 'jsdom',                          globals: true,                                 setupFiles: './src/__tests__/setup.ts',        outputFile: {                                    junit: './project-client.junit.xml',         json: './project-client.report.json',       },       maxWorkers: 4,        minWorkers: 4,      },   } })
  | 
 
重點整理:
| 主題 | 
說明 | 
mode | 
由 CLI 傳入 (development / production),可用 --mode 改變 | 
loadEnv() | 
根據 mode 載入 .env 檔 | 
process.cwd() | 
回傳專案根目錄 | 
tsconfigPaths() | 
讓 Vite 支援 TypeScript 別名 | 
base | 
打包後資源的 URL 前綴 | 
build.outDir | 
打包輸出資料夾 | 
test | 
Vitest 的設定 | 
npm run dev | 
即時開發、HMR 更新 | 
npm run preview | 
模擬正式部署結果 |