Skip to content

🚀 Vite 开发指南

🌟 简介

Vite 是一个现代化的前端构建工具,由 Vue.js 作者尤雨溪开发,旨在提供极速的开发体验和优化的生产构建。Vite 利用浏览器的原生 ES 模块支持,在开发时实现了极速的热更新(HMR),同时通过 Rollup 进行生产构建,确保了优异的构建性能和产物质量。

1.1 Vite 的核心优势

  • 极速开发服务器:利用原生 ES 模块,无需打包,启动速度极快
  • 即时热模块替换:修改代码后立即看到效果,无需等待重新构建
  • 优化的生产构建:使用 Rollup 进行生产构建,产物体积小、性能优
  • 丰富的插件生态:支持各种前端框架和工具
  • 内置 TypeScript 支持:无需额外配置即可使用 TypeScript
  • 智能的路径别名:简化模块导入路径
  • 环境变量管理:内置多环境配置支持

🚀 快速开始

2.1 创建项目

使用 Vite 5 创建新项目的命令如下:

bash
# 使用 npm 6.x
npm create vite@latest my-project -- --template vue

# 使用 npm 7+
npm create vite@latest my-project --template vue

# 使用 yarn
yarn create vite my-project --template vue

# 使用 pnpm
pnpm create vite my-project --template vue

# 使用 bun
bun create vite my-project --template vue

2.2 支持的模板

Vite 提供了多种官方模板,适用于不同的前端框架:

模板名称命令描述
Vue--template vueVue 3 + JavaScript
Vue + TypeScript--template vue-tsVue 3 + TypeScript
React--template reactReact + JavaScript
React + TypeScript--template react-tsReact + TypeScript
React + SWC--template react-swcReact + SWC + JavaScript
React + SWC + TypeScript--template react-swc-tsReact + SWC + TypeScript
Preact--template preactPreact + JavaScript
Preact + TypeScript--template preact-tsPreact + TypeScript
Lit--template litLit + JavaScript
Lit + TypeScript--template lit-tsLit + TypeScript
Svelte--template svelteSvelte + JavaScript
Svelte + TypeScript--template svelte-tsSvelte + TypeScript
Vanilla--template vanilla原生 JavaScript
Vanilla + TypeScript--template vanilla-ts原生 TypeScript

2.3 项目结构

创建项目后,Vite 会生成一个标准的项目结构:

my-project/
├── public/           # 静态资源目录,不会被打包
│   └── favicon.ico   # 网站图标
├── src/              # 源代码目录
│   ├── assets/       # 资源文件(图片、字体等)
│   ├── components/   # 组件目录
│   ├── App.vue       # 根组件
│   └── main.js       # 入口文件
├── index.html        # HTML 入口文件
├── package.json      # 项目配置文件
├── vite.config.js    # Vite 配置文件
├── tsconfig.json     # TypeScript 配置文件(仅 TypeScript 模板)
├── .eslintrc.cjs     # ESLint 配置文件
├── .prettierrc.json  # Prettier 配置文件
└── README.md         # 项目说明文件

2.4 安装依赖并启动开发服务器

bash
# 进入项目目录
cd my-project

# 安装依赖
npm install
# 或 yarn
# yarn install
# 或 pnpm
# pnpm install

# 启动开发服务器
npm run dev
# 或 yarn dev
# 或 pnpm dev

# 构建生产版本
npm run build
# 或 yarn build
# 或 pnpm build

# 预览生产构建产物
npm run preview
# 或 yarn preview
# 或 pnpm preview

✨ 核心特性

3.1 开发服务器

Vite 的开发服务器提供了极速的启动速度和热模块替换(HMR)功能,大大提升了开发体验:

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    // 服务器端口
    port: 3000,
    // 自动打开浏览器
    open: true,
    // 允许跨域
    cors: true,
    // 自定义主机名
    host: '0.0.0.0',
    // 热模块替换配置
    hmr: {
      // 禁用 HMR 覆盖层
      overlay: false,
      // HMR 协议
      protocol: 'ws',
      // HMR 主机
      host: 'localhost'
    },
    // 代理配置
    proxy: {
      // 代理 API 请求
      '/api': {
        // 目标服务器
        target: 'http://localhost:8080',
        // 改变源
        changeOrigin: true,
        // 路径重写
        rewrite: (path) => path.replace(/^\/api/, ''),
        // 配置 WebSocket
        ws: true
      },
      // 多个代理配置
      '/auth': {
        target: 'http://localhost:9000',
        changeOrigin: true
      }
    }
### 3.2 构建优化

Vite 使用 Rollup 进行生产构建,提供了丰富的构建优化选项:

```javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    // 构建目标
    target: 'es2015',
    // 输出目录
    outDir: 'dist',
    // 静态资源目录
    assetsDir: 'assets',
    // 生成源映射
    sourcemap: false,
    // 代码压缩
    minify: 'terser',
    // Terser 配置
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    },
    //  chunk 大小警告阈值
    chunkSizeWarningLimit: 1500,
    // 启用 CSS 代码分割
    cssCodeSplit: true,
    // 生成 manifest.json
    manifest: false,
    // 库模式
    // lib: {
    //   entry: './src/index.js',
    //   name: 'MyLibrary',
    //   fileName: 'my-library'
    // },
    // Rollup 配置
    rollupOptions: {
      // 输入
      input: {
        main: './index.html',
        // 多页面应用
        // admin: './admin.html'
      },
      // 输出
      output: {
        // 手动代码分割
        manualChunks: {
          // 第三方库
          vendor: ['vue', 'vue-router', 'pinia'],
          // 工具库
          utils: ['lodash-es', 'axios'],
          // UI 库
          ui: ['element-plus']
        },
        // 命名格式
        chunkFileNames: 'assets/js/[name]-[hash].js',
        entryFileNames: 'assets/js/[name]-[hash].js',
        assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
      }
    }
  }
});

3.3 预览服务器

Vite 提供了预览服务器,用于本地预览生产构建产物:

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  preview: {
    // 预览端口
    port: 5000,
    // 自动打开浏览器
    open: true,
    // 允许跨域
    cors: true,
    // 代理配置(与开发服务器相同)
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
});

🧩 插件系统

Vite 的插件系统是其生态系统的核心,通过插件可以扩展 Vite 的功能,支持各种前端框架和工具。

4.1 官方插件

Vite 提供了多个官方插件,用于支持不同的前端框架和功能:

javascript
// vite.config.js
import { defineConfig } from 'vite'

// Vue 插件
import vue from '@vitejs/plugin-vue'
// Vue JSX 插件
import vueJsx from '@vitejs/plugin-vue-jsx'
// React 插件
import react from '@vitejs/plugin-react'
// React SWC 插件(更快的编译)
import reactSwc from '@vitejs/plugin-react-swc'
// Preact 插件
import preact from '@vitejs/plugin-preact'
// Lit 插件
import lit from '@vitejs/plugin-lit'
// Svelte 插件
import { svelte } from '@sveltejs/vite-plugin-svelte'
// 传统浏览器兼容性插件
import legacy from '@vitejs/plugin-legacy'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    // 根据项目框架选择相应的插件
    // vue(),
    // react(),
    // preact(),
    // lit(),
    // svelte(),
    
    // Vue JSX 支持
    // vueJsx(),
    
    // 传统浏览器兼容性
    legacy({
      // 目标浏览器
      targets: ['defaults', 'not IE 11'],
      // 生成现代和传统两个版本
      renderLegacyChunks: true,
      //  polyfill 注入方式
      polyfills: ['es.promise.finally', 'es/map', 'es/set'],
      // 现代浏览器检测
      modernPolyfills: true
    })
  ]
});

4.2 常用第三方插件

4.2.1 自动导入插件

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver, AntDesignVueResolver, VantResolver } from 'unplugin-vue-components/resolvers'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    // 自动导入
    AutoImport({
      // 导入预设
      imports: [
        'vue',
        'vue-router',
        'pinia',
        '@vueuse/core'
      ],
      // 解析器
      resolvers: [
        // Element Plus 解析器
        ElementPlusResolver(),
        // Ant Design Vue 解析器
        // AntDesignVueResolver(),
        // Vant 解析器
        // VantResolver(),
        // 图标解析器
        IconsResolver({
          prefix: 'Icon'
        })
      ],
      // 生成 dts 文件
      dts: './auto-imports.d.ts'
    }),
    // 自动导入组件
    Components({
      // 解析器
      resolvers: [
        // Element Plus 解析器
        ElementPlusResolver(),
        // 图标解析器
        IconsResolver({
          enabledCollections: ['ep', 'ant-design', 'material', 'lucide']
        })
      ],
      // 生成 dts 文件
      dts: './components.d.ts'
    }),
    // 图标插件
    Icons({
      autoInstall: true,
      compiler: 'vue3'
    })
  ]
});

4.2.2 路径别名插件

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    // 路径别名
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
      '@assets': path.resolve(__dirname, './src/assets'),
      '@utils': path.resolve(__dirname, './src/utils'),
      '@api': path.resolve(__dirname, './src/api'),
      '@store': path.resolve(__dirname, './src/store')
    },
    // 扩展名
    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
  }
});

4.2.3 其他实用插件

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
import { compression } from 'vite-plugin-compression'
import { visualizer } from 'rollup-plugin-visualizer'
import htmlPurge from 'vite-plugin-purge-icons'
import eslint from 'vite-plugin-eslint'
import stylelint from 'vite-plugin-stylelint'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    // ESLint 插件
    eslint({
      cache: false,
      include: ['src/**/*.{js,jsx,ts,tsx,vue}']
    }),
    // StyleLint 插件
    stylelint({
      fix: true,
      include: ['src/**/*.{css,scss,sass,less,stylus,vue}']
    }),
    // PWA 插件
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico', 'apple-touch-icon.png', 'masked-icon.svg'],
      manifest: {
        name: 'My App',
        short_name: 'My App',
        description: 'My Awesome App',
        theme_color: '#ffffff',
        icons: [
          {
            src: 'pwa-192x192.png',
            sizes: '192x192',
            type: 'image/png'
          },
          {
            src: 'pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png'
          }
        ]
      }
    }),
    // 压缩插件
    compression({
      algorithm: 'gzip',
      ext: '.gz',
      threshold: 10240
    }),
    // 构建分析插件
    visualizer({
      open: true,
      gzipSize: true,
      brotliSize: true
    }),
    // 图标清理插件
    htmlPurge()
  ]
});

🌍 环境配置

Vite 提供了内置的环境变量管理功能,支持多环境配置,方便在不同环境下使用不同的配置。

5.1 环境变量文件

Vite 支持以下环境变量文件:

bash
# .env                # 所有环境通用
# .env.local          # 所有环境通用,不会被提交到版本控制
# .env.development    # 开发环境
# .env.development.local  # 开发环境,不会被提交到版本控制
# .env.production     # 生产环境
# .env.production.local  # 生产环境,不会被提交到版本控制
# .env.test           # 测试环境
# .env.test.local     # 测试环境,不会被提交到版本控制

5.2 环境变量配置

bash
# .env
# 应用标题
VITE_APP_TITLE=My App
# 应用版本
VITE_APP_VERSION=1.0.0
# API 基础 URL
VITE_API_BASE_URL=http://api.example.com
# 是否开启调试模式
VITE_APP_DEBUG=false

# .env.development
# 开发环境 API URL
VITE_API_BASE_URL=http://localhost:8080
# 开发环境开启调试模式
VITE_APP_DEBUG=true

# .env.production
# 生产环境 API URL
VITE_API_BASE_URL=https://api.production.com
# 生产环境关闭调试模式
VITE_APP_DEBUG=false

# .env.test
# 测试环境 API URL
VITE_API_BASE_URL=http://api.test.com
# 测试环境开启调试模式
VITE_APP_DEBUG=true

5.3 环境变量使用

在代码中,Vite 提供了 import.meta.env 对象来访问环境变量:

javascript
// 在组件中使用环境变量
<template>
  <div>
    <h1>{{ appTitle }}</h1>
    <p>版本: {{ appVersion }}</p>
    <p>API URL: {{ apiBaseUrl }}</p>
    <p v-if="isDebug">调试模式已开启</p>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

// 访问环境变量
const appTitle = import.meta.env.VITE_APP_TITLE
const appVersion = import.meta.env.VITE_APP_VERSION
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL
const isDebug = import.meta.env.VITE_APP_DEBUG === 'true'

// 计算属性
const apiUrl = computed(() => {
  return `${apiBaseUrl}/v1`
})

console.log('应用标题:', appTitle)
console.log('API URL:', apiUrl.value)
</script>

// 在 API 配置中使用环境变量
// api/config.js
export const API_CONFIG = {
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json'
  }
}

// 在路由配置中使用环境变量
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'Home',
      component: () => import('../views/Home.vue')
    },
    // 条件路由配置
    ...(import.meta.env.VITE_APP_DEBUG === 'true' ? [
      {
        path: '/debug',
        name: 'Debug',
        component: () => import('../views/Debug.vue')
      }
    ] : [])
  ]
})

5.4 内置环境变量

Vite 提供了以下内置环境变量:

javascript
// 是否为开发环境
import.meta.env.DEV  // 开发环境为 true

// 是否为生产环境
import.meta.env.PROD // 生产环境为 true

// 是否为 SSR 环境
import.meta.env.SSR  // SSR 环境为 true

// 应用的基础路径
import.meta.env.BASE_URL // 对应 vite.config.js 中的 base 配置

// 项目根目录的绝对路径
import.meta.env.PROJECT_ROOT // 仅在开发环境可用

// 构建时间戳
import.meta.env.BUILD_TIMESTAMP // 仅在生产环境可用

5.5 自定义环境变量类型

在 TypeScript 项目中,可以通过类型声明文件来定义环境变量的类型:

typescript
// src/vite-env.d.ts
/// <reference types="vite/client" />

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

// 自定义环境变量类型
enum AppEnvironment {
  Development = 'development',
  Production = 'production',
  Test = 'test'
}

declare interface ImportMetaEnv {
  // 应用标题
  readonly VITE_APP_TITLE: string
  // 应用版本
  readonly VITE_APP_VERSION: string
  // API 基础 URL
  readonly VITE_API_BASE_URL: string
  // 是否开启调试模式
  readonly VITE_APP_DEBUG: string
  // 应用环境
  readonly VITE_APP_ENV: AppEnvironment
}

declare interface ImportMeta {
  readonly env: ImportMetaEnv
}

📦 资源处理

Vite 提供了强大的资源处理能力,支持各种类型的静态资源和 CSS 预处理器。

6.1 静态资源

6.1.1 静态资源配置

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 静态资源目录
  publicDir: 'public',
  // 静态资源包含
  assetsInclude: [
    '**/*.gltf',  // 3D 模型
    '**/*.glb',   // 3D 模型
    '**/*.obj',   // 3D 模型
    '**/*.fbx',   // 3D 模型
    '**/*.mp4',   // 视频
    '**/*.webm',  // 视频
    '**/*.ogg',   // 音频
    '**/*.mp3',   // 音频
    '**/*.wav',   // 音频
    '**/*.woff',  // 字体
    '**/*.woff2', // 字体
    '**/*.ttf',   // 字体
    '**/*.eot'    // 字体
  ]
});

6.1.2 静态资源使用

Vite 支持多种方式使用静态资源:

javascript
// 1. 导入图片
import logo from './assets/logo.png'

// 在组件中使用
<template>
  <img :src="logo" alt="Logo" />
</template>

// 2. 导入样式
import './assets/styles/main.css'

// 3. 导入 JSON
import config from './config.json'
console.log(config.apiUrl)

// 4. 导入 Web Worker
import MyWorker from './worker?worker'
const worker = new MyWorker()
worker.postMessage({ type: 'ping' })

// 5. 导入 WebAssembly
import init from './module.wasm'
init().then((exports) => {
  console.log(exports.add(1, 2))
})

// 6. 动态导入
const loadImage = async () => {
  const { default: image } = await import('./assets/dynamic-image.png')
  return image
}

// 7. 使用 public 目录下的资源
// public 目录下的资源会被直接复制到输出目录,无需导入
// 使用绝对路径访问
<img src="/favicon.ico" alt="Favicon" />

6.2 CSS 处理

6.2.1 CSS 预处理器配置

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  css: {
    // 启用 CSS 模块
    modules: {
      // 自定义 CSS 模块类名
      generateScopedName: '[name]__[local]--[hash:base64:5]'
    },
    // 预处理器配置
    preprocessorOptions: {
      // SCSS 配置
      scss: {
        // 全局变量和混合
        additionalData: `
          @import "@/styles/variables.scss";
          @import "@/styles/mixins.scss";
        `
      },
      // Less 配置
      less: {
        math: 'always',
        globalVars: {
          '@primary-color': '#42b983'
        }
      },
      // Stylus 配置
      stylus: {
        define: {
          $primary-color: '#42b983'
        }
      }
    },
    // 启用 CSS 源映射
    devSourcemap: true
  }
});

6.2.2 CSS 模块使用

vue
<!-- 组件样式 -->
<style module>
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.title {
  font-size: 24px;
  color: var(--primary-color);
}
</style>

<template>
  <div :class="$style.container">
    <h1 :class="$style.title">Hello Vite</h1>
  </div>
</template>

<script setup>
// 也可以使用具名导入
import styles from './Component.module.css'
</script>

<template>
  <div :class="styles.container">
    <h1 :class="styles.title">Hello Vite</h1>
  </div>
</template>

6.2.3 PostCSS 配置

Vite 默认集成了 PostCSS,可以通过 postcss.config.js 文件进行配置:

javascript
// postcss.config.js
module.exports = {
  plugins: {
    // 自动添加浏览器前缀
    autoprefixer: {},
    // CSS 嵌套
    'postcss-nested': {},
    // CSS 变量
    'postcss-custom-properties': {},
    // CSS 导入
    'postcss-import': {},
    // CSS 压缩
    cssnano: process.env.NODE_ENV === 'production' ? {
      preset: 'default'
    } : false
  }
}

⚡ 性能优化

Vite 提供了多种性能优化选项,包括开发时优化和构建时优化。

7.1 构建优化

7.1.1 代码分割

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    // chunk 大小警告阈值
    chunkSizeWarningLimit: 1500,
    // 启用 CSS 代码分割
    cssCodeSplit: true,
    // 启用动态导入的代码分割
    dynamicImportVars: true,
    // Rollup 配置
    rollupOptions: {
      output: {
        // 手动代码分割
        manualChunks: {
          // 第三方库
          vendor: ['vue', 'vue-router', 'pinia'],
          // 工具库
          utils: ['lodash-es', 'axios', '@vueuse/core'],
          // UI 库
          ui: ['element-plus', '@element-plus/icons-vue'],
          // 图表库
          charts: ['echarts'],
          // 地图库
          maps: ['amap-jsapi-loader']
        },
        // 命名格式
        chunkFileNames: 'assets/js/[name]-[hash].js',
        entryFileNames: 'assets/js/[name]-[hash].js',
        assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
      }
    }
  }
});

7.1.2 构建输出优化

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    // 构建目标
    target: 'es2015',
    // 输出目录
    outDir: 'dist',
    // 静态资源目录
    assetsDir: 'assets',
    // 生成源映射
    sourcemap: false,
    // 代码压缩
    minify: 'terser',
    // Terser 配置
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
        // 移除未使用的变量和函数
        unused: true,
        // 合并变量
        collapse_vars: true,
        // 内联函数
        inline: true
      },
      mangle: {
        // 混淆变量名
        toplevel: true,
        // 保留关键字
        reserved: ['$', 'jQuery']
      }
    },
    // 清除输出目录
    emptyOutDir: true,
    // 产物分析
    reportCompressedSize: true
  }
});

7.2 开发优化

7.2.1 依赖预构建

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 依赖预构建
  optimizeDeps: {
    // 需要预构建的依赖
    include: [
      'lodash-es',
      'axios',
      'echarts',
      '@vueuse/core',
      'element-plus'
    ],
    // 排除不需要预构建的依赖
    exclude: [
      'vue',
      'vue-router',
      'pinia'
    ],
    // 强制预构建
    force: false,
    // 预构建输出目录
    esbuildOptions: {
      // 目标
      target: 'es2015',
      // 定义全局变量
      define: {
        'process.env.NODE_ENV': JSON.stringify('development')
      }
    }
  },
  // 服务器配置
  server: {
    // 热模块替换
    hmr: {
      // 禁用 HMR 覆盖层
      overlay: false,
      // 启用 HMR 内联
      clientPort: 3000
    },
    // 启动时打开浏览器
    open: true,
    // 端口
    port: 3000
  }
});

7.2.2 缓存优化

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 缓存目录
  cacheDir: '.vite',
  // 构建缓存
  build: {
    // 缓存
    cache: {
      // 启用缓存
      enabled: true,
      // 缓存目录
      directory: '.vite/build'
    }
  },
  // 服务器缓存
  server: {
    // 启用文件系统缓存
    fs: {
      // 允许访问的文件
      allow: ['..']
    }
  }
});

7.3 资源优化

7.3.1 图片优化

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    // SVG 图标插件
    createSvgIconsPlugin({
      // SVG 图标目录
      iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
      // 图标 ID 格式
      symbolId: 'icon-[dir]-[name]'
    })
  ],
  // 构建配置
  build: {
    // 资产优化
    assetsInlineLimit: 4096, // 4kb 以下的资源内联
    // 空出目录
    emptyOutDir: true
  }
});

7.3.2 CSS 优化

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  css: {
    // 启用 CSS 模块
    modules: true,
    // 启用 CSS 源映射
    devSourcemap: true,
    // 预处理器配置
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/variables.scss";`
      }
    }
  },
  build: {
    // 启用 CSS 代码分割
    cssCodeSplit: true,
    // CSS 提取
    cssMinify: 'lightningcss'
  }
});

🎯 最佳实践

8.1 项目结构

8.1.1 推荐的项目结构

my-project/
├── public/                 # 静态资源目录
│   ├── favicon.ico         # 网站图标
│   └── robots.txt          # 搜索引擎配置
├── src/                    # 源代码目录
│   ├── assets/             # 资源文件
│   │   ├── icons/          # SVG 图标
│   │   ├── images/         # 图片
│   │   ├── fonts/          # 字体
│   │   └── styles/         # 全局样式
│   ├── components/         # 组件
│   │   ├── common/         # 通用组件
│   │   ├── layout/         # 布局组件
│   │   └── business/       # 业务组件
│   ├── composables/        # 组合式 API
│   ├── directives/         # 自定义指令
│   ├── filters/            # 过滤器
│   ├── hooks/              # 自定义钩子
│   ├── layouts/            # 布局
│   ├── plugins/            # 插件
│   ├── router/             # 路由
│   │   ├── index.js        # 路由配置
│   │   └── guards.js       # 路由守卫
│   ├── stores/             # 状态管理
│   │   ├── modules/        # 状态模块
│   │   └── index.js        # 状态配置
│   ├── services/           # 服务
│   │   ├── api/            # API 服务
│   │   └── utils/          # 工具服务
│   ├── utils/              # 工具函数
│   ├── views/              # 页面
│   ├── App.vue             # 根组件
│   └── main.js             # 入口文件
├── tests/                  # 测试
│   ├── unit/               # 单元测试
│   └── e2e/                # 端到端测试
├── config/                 # 配置
│   ├── vite/               # Vite 配置
│   │   ├── base.js         # 基础配置
│   │   ├── dev.js          # 开发配置
│   │   └── prod.js         # 生产配置
│   └── index.js            # 配置入口
├── scripts/                # 脚本
│   ├── build.js            # 构建脚本
│   └── deploy.js           # 部署脚本
├── index.html              # HTML 入口
├── package.json            # 项目配置
├── vite.config.js          # Vite 配置
├── tsconfig.json           # TypeScript 配置
├── tsconfig.node.json      # Node.js TypeScript 配置
├── .eslintrc.cjs           # ESLint 配置
├── .prettierrc.json        # Prettier 配置
├── .stylelintrc.json       # StyleLint 配置
├── .gitignore              # Git 忽略文件
└── README.md               # 项目说明

8.1.2 模块化配置文件

javascript
// config/vite/base.js
import { defineConfig } from 'vite'
import path from 'path'

// 基础配置
export default defineConfig({
  // 路径别名
  resolve: {
    alias: {
      '@': path.resolve(__dirname, '../../src'),
      '@components': path.resolve(__dirname, '../../src/components'),
      '@assets': path.resolve(__dirname, '../../src/assets'),
      '@utils': path.resolve(__dirname, '../../src/utils'),
      '@api': path.resolve(__dirname, '../../src/services/api'),
      '@store': path.resolve(__dirname, '../../src/stores')
    }
  },
  // 插件配置
  plugins: []
});

// config/vite/dev.js
import { defineConfig } from 'vite'

// 开发配置
export default defineConfig({
  server: {
    port: 3000,
    open: true,
    cors: true,
    hmr: {
      overlay: false
    }
  }
});

// config/vite/prod.js
import { defineConfig } from 'vite'

// 生产配置
export default defineConfig({
  build: {
    target: 'es2015',
    minify: 'terser',
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['vue', 'vue-router', 'pinia'],
          utils: ['lodash-es', 'axios']
        }
      }
    }
  }
});

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import baseConfig from './config/vite/base'
import devConfig from './config/vite/dev'
import prodConfig from './config/vite/prod'

// 合并配置
const mergedConfig = defineConfig({
  ...baseConfig,
  plugins: [
    vue(),
    ...baseConfig.plugins
  ],
  ...(process.env.NODE_ENV === 'development' ? devConfig : prodConfig)
});

export default mergedConfig

8.2 开发流程

8.2.1 使用 TypeScript

typescript
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,

    /* Path aliases */
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

// tsconfig.node.json
{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}

// src/vite-env.d.ts
/// <reference types="vite/client" />

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

8.2.2 代码规范

javascript
// .eslintrc.cjs
module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier'
  ],
  parserOptions: {
    ecmaVersion: 2021,
    parser: '@typescript-eslint/parser',
    sourceType: 'module'
  },
  plugins: [
    'vue',
    '@typescript-eslint'
  ],
  rules: {
    // 自定义规则
    'vue/multi-word-component-names': 'off',
    '@typescript-eslint/no-explicit-any': 'off'
  }
}

// .prettierrc.json
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2
}

// .stylelintrc.json
{
  "extends": [
    "stylelint-config-standard",
    "stylelint-config-prettier"
  ],
  "rules": {
    // 自定义规则
    "selector-class-pattern": "^[a-z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$",
    "declaration-no-important": true
  }
}

// package.json 脚本
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
    "format": "prettier --write .",
    "stylelint": "stylelint \"**/*.{css,scss,sass,less,stylus,vue}\" --fix",
    "typecheck": "tsc --noEmit",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage"
  }
}

8.2.3 自动化测试

javascript
// jest.config.js
module.exports = {
  preset: '@vue/cli-plugin-unit-jest/presets/typescript',
  testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[tj]s?(x)'],
  collectCoverageFrom: [
    'src/**/*.{vue,js,jsx,ts,tsx}',
    '!src/main.ts',
    '!src/App.vue',
    '!src/router/index.ts',
    '!src/stores/index.ts',
    '!**/node_modules/**',
    '!**/dist/**'
  ],
  coverageDirectory: '<rootDir>/coverage',
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  }
}

// 示例测试文件
// src/components/HelloWorld.spec.ts
import { mount } from '@vue/test-utils'
import HelloWorld from './HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const wrapper = mount(HelloWorld, {
      props: { msg }
    })
    expect(wrapper.text()).toMatch(msg)
  })

  it('renders the default message when no msg is passed', () => {
    const wrapper = mount(HelloWorld)
    expect(wrapper.text()).toMatch('Hello World')
  })
})

8.3 性能优化

8.3.1 合理使用插件

  • 只使用必要的插件:插件会增加构建时间和复杂度,只使用项目真正需要的插件
  • 使用官方插件:官方插件经过优化,性能更好
  • 合理配置插件:根据项目需求配置插件,避免不必要的功能
  • 使用插件的按需加载:如 UI 库的按需加载

8.3.2 优化构建配置

  • 代码分割:使用 manualChunks 合理分割代码
  • 资源内联:小资源内联,减少 HTTP 请求
  • 代码压缩:使用 terseresbuild 压缩代码
  • Tree Shaking:移除未使用的代码
  • 懒加载:使用动态导入懒加载组件和路由

8.3.3 实施缓存策略

  • 浏览器缓存:使用长效缓存策略,为静态资源添加哈希值
  • 构建缓存:启用 Vite 的构建缓存
  • 依赖缓存:使用 optimizeDeps 预构建依赖
  • CDN 缓存:合理配置 CDN 缓存策略

8.3.4 开发体验优化

  • 热模块替换:启用 HMR,提高开发效率
  • 快速启动:使用 Vite 的极速开发服务器
  • 错误提示:配置友好的错误提示
  • 代码智能提示:使用 TypeScript 和编辑器插件

8.4 部署策略

8.4.1 多环境部署

javascript
// package.json 脚本
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "build:dev": "vite build --mode development",
    "build:test": "vite build --mode test",
    "build:prod": "vite build --mode production",
    "preview": "vite preview"
  }
}

// 部署脚本示例
// scripts/deploy.js
const { execSync } = require('child_process')
const fs = require('fs')
const path = require('path')

// 部署环境
const env = process.argv[2] || 'production'

console.log(`开始部署到 ${env} 环境...`)

// 构建
console.log('正在构建...')
execSync(`npm run build:${env}`, { stdio: 'inherit' })

// 部署到服务器
console.log('正在部署到服务器...')
// 这里根据实际部署方式修改
execSync('scp -r dist/* user@server:/path/to/destination', { stdio: 'inherit' })

console.log('部署完成!')

8.4.2 Docker 部署

dockerfile
# Dockerfile
FROM node:18-alpine as build

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package-lock.json
COPY package*.json ./

# 安装依赖
RUN npm install

# 复制源代码
COPY . .

# 构建生产版本
RUN npm run build

# 使用 Nginx 作为基础镜像
FROM nginx:alpine

# 复制构建产物到 Nginx 目录
COPY --from=build /app/dist /usr/share/nginx/html

# 复制 Nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 暴露端口
EXPOSE 80

# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]

# nginx.conf
server {
    listen 80;
    server_name localhost;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /api {
        proxy_pass http://api-server:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# docker-compose.yml
version: '3'
services:
  frontend:
    build: .
    ports:
      - "80:80"
    depends_on:
      - api-server
  api-server:
    image: your-api-server-image
    ports:
      - "8080:8080"

❓ 常见问题

9.1 热更新问题

9.1.1 HMR 不生效

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    // 确保 HMR 连接正确
    hmr: {
      // HMR 协议
      protocol: 'ws',
      // HMR 主机
      host: 'localhost',
      // HMR 端口
      port: 3000,
      // 禁用 HMR 覆盖层
      overlay: true,
      // 启用 HMR 内联
      clientPort: 3000
    },
    // 确保服务器主机配置正确
    host: '0.0.0.0',
    port: 3000
  }
});

9.1.2 网络环境问题

  • 问题:在局域网或远程开发环境中,HMR 可能不生效
  • 解决方案:配置 clientPorthost 选项
javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    // 允许所有主机访问
    host: true,
    // 端口
    port: 3000,
    // 热更新配置
    hmr: {
      // 客户端端口
      clientPort: 3000,
      // 禁用覆盖层
      overlay: false
    }
  }
});

9.2 路径别名问题

9.2.1 TypeScript 路径别名

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    // 路径别名
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
      '@assets': path.resolve(__dirname, './src/assets')
    }
  }
});

// tsconfig.json
{
  "compilerOptions": {
    // 其他配置...
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@assets/*": ["src/assets/*"]
    }
  }
}

9.2.2 路径别名不生效

  • 问题:在某些情况下,路径别名可能不生效
  • 解决方案
    1. 确保 vite.config.js 中的别名配置正确
    2. 确保 tsconfig.json 中的路径配置与 Vite 配置一致
    3. 重启开发服务器
    4. 检查是否有拼写错误

9.3 依赖预构建问题

9.3.1 依赖预构建失败

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 依赖预构建配置
  optimizeDeps: {
    // 需要预构建的依赖
    include: [
      'lodash-es',
      'axios',
      'echarts'
    ],
    // 排除不需要预构建的依赖
    exclude: [
      'vue',
      'vue-router'
    ],
    // 强制预构建
    force: true
  }
});

9.3.2 依赖缓存问题

  • 问题:依赖预构建缓存导致的问题
  • 解决方案
    1. 删除 .vite 目录,重新启动开发服务器
    2. vite.config.js 中设置 force: true 强制重新预构建
    3. 检查依赖版本是否正确

9.4 构建问题

9.4.1 构建失败

javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    // 构建目标
    target: 'es2015',
    // 输出目录
    outDir: 'dist',
    // 清除输出目录
    emptyOutDir: true,
    // 生成源映射
    sourcemap: false,
    // 代码压缩
    minify: 'terser',
    // 禁用 CSS 代码分割
    cssCodeSplit: true,
    // 禁用动态导入的代码分割
    dynamicImportVars: true
  }
});

9.4.2 构建产物过大

  • 问题:构建产物过大,影响加载速度
  • 解决方案
    1. 使用代码分割,合理分割代码
    2. 启用 Tree Shaking,移除未使用的代码
    3. 使用按需加载,减少初始加载体积
    4. 优化图片和静态资源
    5. 使用 CDN 加载第三方库

9.5 环境变量问题

9.5.1 环境变量不生效

  • 问题:环境变量在代码中不生效
  • 解决方案
    1. 确保环境变量文件命名正确(如 .env.development
    2. 确保环境变量以 VITE_ 前缀开头
    3. 重启开发服务器
    4. 检查环境变量文件是否被忽略(如 .gitignore

9.5.2 环境变量类型问题

typescript
// src/vite-env.d.ts
/// <reference types="vite/client" />

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

// 自定义环境变量类型
declare interface ImportMetaEnv {
  readonly VITE_APP_TITLE: string
  readonly VITE_API_BASE_URL: string
  readonly VITE_APP_DEBUG: string
}

declare interface ImportMeta {
  readonly env: ImportMetaEnv
}

9.6 其他常见问题

9.6.1 浏览器兼容性

  • 问题:构建产物在某些浏览器中不兼容
  • 解决方案:使用 @vitejs/plugin-legacy 插件
javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import legacy from '@vitejs/plugin-legacy'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    legacy({
      targets: ['defaults', 'not IE 11'],
      renderLegacyChunks: true,
      polyfills: ['es.promise.finally', 'es/map', 'es/set']
    })
  ]
});

9.6.2 静态资源加载

  • 问题:静态资源加载失败
  • 解决方案
    1. 检查资源路径是否正确
    2. 确保资源文件存在
    3. 配置 publicDirassetsInclude 选项
javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 静态资源目录
  publicDir: 'public',
  // 静态资源包含
  assetsInclude: ['**/*.gltf', '**/*.glb', '**/*.mp4']
});

🎉 总结

Vite 作为现代前端构建工具的代表,以其极速的开发体验和优化的构建输出,已经成为前端开发的首选工具之一。通过本文的学习,我们了解了 Vite 的核心特性、配置选项和最佳实践,可以更好地利用 Vite 提升开发效率和构建质量。

核心优势回顾

  • 极速开发服务器:利用原生 ES 模块,无需打包,启动速度极快
  • 即时热模块替换:修改代码后立即看到效果,无需等待重新构建
  • 优化的生产构建:使用 Rollup 进行生产构建,产物体积小、性能优
  • 丰富的插件生态:支持各种前端框架和工具
  • 内置 TypeScript 支持:无需额外配置即可使用 TypeScript
  • 智能的路径别名:简化模块导入路径
  • 环境变量管理:内置多环境配置支持

最佳实践总结

  1. 项目结构:使用清晰的目录结构,模块化配置文件
  2. 开发流程:使用 TypeScript,实施代码规范,自动化测试
  3. 性能优化:合理使用插件,优化构建配置,实施缓存策略
  4. 部署策略:多环境部署,Docker 部署,CDN 缓存

未来展望

Vite 团队不断迭代更新,为前端开发带来更多惊喜:

  • Vite 5:带来了更快的构建速度和更小的构建产物
  • Vite SSR:服务端渲染支持
  • Vite PWA:渐进式 Web 应用支持
  • Vite 插件生态:越来越丰富的插件生态

通过合理使用 Vite,我们可以构建出更高效、更可维护的前端应用,为用户提供更好的体验。

📚 参考资源

10.1 官方文档

10.2 学习资源

10.2.1 教程

10.2.2 视频教程

10.2.3 博客和文章

10.3 工具和插件

10.3.1 官方插件

10.3.2 第三方插件

10.4 社区和论坛

10.5 相关工具

通过这些资源,你可以更深入地了解 Vite,掌握其高级用法,为你的前端开发之旅增添助力。

Vite 通过其快速的开发服务器和优化的构建流程,为现代前端开发提供了极佳的开发体验。通过合理配置和最佳实践,可以充分发挥 Vite 的优势。

参考资源