跳至內容

Vite 專案效能最佳化實戰指南

Vite 的開發體驗真的很爽快,但實際專案跑起來還是有不少可以調校的地方。這篇文章整理了我在開發和生產環境中優化 Vite 專案的一些實用技巧。


開發環境最佳化

1. 依賴預建構(Dependency Pre-Bundling)

Vite 會自動預建構依賴,但我們可以透過配置加速這個過程:

javascript
// vite.config.js
export default {
  optimizeDeps: {
    // 明確指定需要預建構的依賴
    include: [
      'vue',
      'vue-router',
      'pinia',
      'axios',
      // 深層依賴也可以指定
      'lodash-es'
    ],
    // 排除不需要預建構的依賴
    exclude: ['@vueuse/core']
  }
}

為什麼要這樣做?

  • 減少首次啟動時的依賴掃描時間
  • 避免某些套件在運行時被重複轉換
  • 特別是對於有大量依賴的專案,可以明顯提升啟動速度

2. 模組熱更新(HMR)最佳化

合理的元件拆分可以提升 HMR 的效率:

javascript
// ❌ 不好的做法:單一巨大檔案
// App.vue 包含所有邏輯、樣式、子元件

// ✅ 好的做法:拆分元件和樣式
// App.vue
import Header from './components/Header.vue'
import Content from './components/Content.vue'
import Footer from './components/Footer.vue'

技巧:

  • 將大型元件拆分成更小的單元
  • 樣式檔案獨立管理,避免 CSS 和 JS 綁定
  • 使用 <script setup> 語法,Vite 對其有更好的 HMR 支援

3. 路徑別名配置

設定路徑別名不僅提升開發體驗,也能加速模組解析:

js
// vite.config.js
import { fileURLToPath, URL } from 'node:url'

export default {
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      '@components': fileURLToPath(new URL('./src/components', import.meta.url)),
      '@utils': fileURLToPath(new URL('./src/utils', import.meta.url))
    }
  }
}

生產環境最佳化

1. Code Splitting 策略

路由層級的分割

javascript
// router/index.js
const routes = [
  {
    path: '/dashboard',
    // 使用動態 import
    component: () => import('@/views/Dashboard.vue')
  },
  {
    path: '/settings',
    component: () => import('@/views/Settings.vue')
  }
]

元件層級的分割

vue
<script setup>
import { defineAsyncComponent } from 'vue'

// 大型元件使用 lazy loading
const HeavyChart = defineAsyncComponent(() =>
  import('@/components/HeavyChart.vue')
)
</script>

手動分割 chunk

javascript
// vite.config.js
export default {
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          // 將 Vue 生態系分離出來
          'vue-vendor': ['vue', 'vue-router', 'pinia'],
          // UI 框架獨立打包
          'ui-vendor': ['element-plus'],
          // 工具函式庫
          'utils': ['lodash-es', 'dayjs']
        }
      }
    }
  }
}

為什麼要分割 chunk?

  • 提升瀏覽器快取效率
  • 第三方庫變動頻率低,分離後可以長期快取
  • 減少首次載入的 bundle 大小

2. 壓縮與最佳化

Gzip/Brotli 壓縮

javascript
// vite.config.js
import viteCompression from 'vite-plugin-compression'

export default {
  plugins: [
    viteCompression({
      algorithm: 'gzip',
      ext: '.gz'
    }),
    viteCompression({
      algorithm: 'brotliCompress',
      ext: '.br'
    })
  ]
}

CSS 最佳化

javascript
export default {
  css: {
    // 生產環境移除未使用的 CSS
    postcss: {
      plugins: [
        require('autoprefixer'),
        require('cssnano')({
          preset: 'default'
        })
      ]
    }
  }
}

3. 圖片最佳化

使用 Vite 插件處理圖片:

javascript
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'

export default {
  plugins: [
    ViteImageOptimizer({
      png: {
        quality: 80
      },
      jpeg: {
        quality: 80
      },
      webp: {
        quality: 80
      }
    })
  ]
}

實務建議:

vue
<template>
  <!-- 使用現代圖片格式 -->
  <picture>
    <source srcset="/images/hero.webp" type="image/webp">
    <source srcset="/images/hero.jpg" type="image/jpeg">
    <img src="/images/hero.jpg" alt="Hero image">
  </picture>
</template>

4. Tree Shaking 最佳化

確保套件支援 tree shaking:

javascript
// ❌ 不利於 tree shaking
import _ from 'lodash'

// ✅ 使用 ES modules 版本
import { debounce, throttle } from 'lodash-es'

// ✅ 直接引用需要的函式
import debounce from 'lodash-es/debounce'

Build 效能最佳化

1. 使用 esbuild 或 SWC

javascript
export default {
  build: {
    // 使用 esbuild 壓縮(預設)
    minify: 'esbuild',
    // 或使用 terser 獲得更好的壓縮率
    // minify: 'terser',
  }
}

2. 平行處理

javascript
export default {
  build: {
    // 啟用多執行緒建構
    terserOptions: {
      compress: {
        parallel: true
      }
    }
  }
}

3. Source Map 策略

javascript
export default {
  build: {
    // 開發環境使用完整 source map
    sourcemap: process.env.NODE_ENV === 'development' ? true : false,
    // 生產環境可以選擇隱藏或使用輕量版
    // sourcemap: 'hidden'
  }
}

效能監控

使用 Vite Bundle Analyzer

javascript
import { visualizer } from 'rollup-plugin-visualizer'

export default {
  plugins: [
    visualizer({
      open: true,
      gzipSize: true,
      brotliSize: true
    })
  ]
}

這會生成一個互動式的 bundle 分析圖,幫助你找出可以最佳化的部分。

實際案例:專案最佳化前後對比

在一個中型專案中,應用上述技巧後的效果:

開發環境:

  • 啟動時間:從 3.2s 降至 1.8s(44% 提升)
  • HMR 更新:從 800ms 降至 200ms

生產環境:

  • 首次載入時間:從 2.1s 降至 1.2s
  • Bundle 大小:從 850KB 降至 420KB(使用 gzip)

總結

優化 Vite 專案主要抓住幾個重點:

  1. 開發環境:專注於啟動速度和 HMR 效率
  2. 生產環境:著重於 bundle 大小和載入效能
  3. 持續監控:使用分析工具找出瓶頸

效能優化是個持續的過程,要看專案實際狀況來調整。記住一個原則:不要過早優化,先用工具找出真正的瓶頸在哪裡,再針對性地解決。

我的建議是養成定期檢查 bundle 分析的習慣,這樣才能確保效能不會隨著專案成長而越來越糟。

💬 留言討論

Released under the MIT License.