Skip to content

Vite 深度解析

Vite 利用浏览器原生 ESM 和 esbuild 预构建,实现了毫秒级冷启动和极速 HMR,彻底改变了前端开发体验。

为什么 Vite 这么快

传统打包工具(Webpack)开发模式:
  所有模块 → Bundle → 启动 Dev Server
  问题:项目越大,启动越慢(几十秒甚至更长)

Vite 开发模式:
  启动 Dev Server(立即)
  浏览器请求模块 → 按需转换 → 返回 ESM
  
  依赖(node_modules)→ esbuild 预构建(Go 编写,极快)→ 缓存
  源码(.vue/.tsx)   → 浏览器请求时按需转换

核心配置

ts
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'
import vue from '@vitejs/plugin-vue'
import path from 'path'

export default defineConfig(({ command, mode }) => {
  const env = loadEnv(mode, process.cwd(), '')

  return {
    plugins: [
      react(),  // 或 vue()
    ],

    // 路径别名
    resolve: {
      alias: {
        '@': path.resolve(__dirname, './src'),
        '@components': path.resolve(__dirname, './src/components'),
      }
    },

    // 开发服务器
    server: {
      port: 3000,
      open: true,
      // 代理:解决开发环境跨域
      proxy: {
        '/api': {
          target: 'http://localhost:8080',
          changeOrigin: true,
          rewrite: path => path.replace(/^\/api/, '')
        }
      }
    },

    // 构建配置
    build: {
      outDir: 'dist',
      sourcemap: true,
      // 代码分割
      rollupOptions: {
        output: {
          manualChunks: {
            vendor: ['react', 'react-dom'],
            router: ['react-router-dom'],
          }
        }
      },
      // chunk 大小警告阈值
      chunkSizeWarningLimit: 500
    },

    // CSS 配置
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: `@import "@/styles/variables.scss";`
        }
      },
      modules: {
        localsConvention: 'camelCase'
      }
    },

    // 环境变量
    define: {
      __APP_VERSION__: JSON.stringify(process.env.npm_package_version)
    }
  }
})

HMR 原理

文件变化 → Vite 服务器检测 → 计算最小更新范围 → 通过 WebSocket 推送

HMR 边界(HMR Boundary):
  如果 Button.vue 变化:
    Button.vue 接受自身更新 → 只替换 Button 模块
    如果不接受 → 向上冒泡到 App.vue
    如果没有边界 → 全页面刷新

Vue/React 插件自动处理 HMR,无需手动配置。

手动处理 HMR(自定义模块):
if (import.meta.hot) {
  import.meta.hot.accept('./module.js', (newModule) => {
    // 使用新模块
  })
  import.meta.hot.dispose(() => {
    // 清理副作用
  })
}

插件开发

ts
// 自定义 Vite 插件
import type { Plugin } from 'vite'

function myPlugin(): Plugin {
  return {
    name: 'my-plugin',

    // 构建钩子(与 Rollup 兼容)
    buildStart() {
      console.log('构建开始')
    },

    // 转换文件内容
    transform(code, id) {
      if (!id.endsWith('.ts')) return
      // 转换代码...
      return { code: transformedCode, map: sourceMap }
    },

    // 解析模块 ID
    resolveId(id) {
      if (id === 'virtual:my-module') {
        return '\0virtual:my-module'  // \0 前缀表示虚拟模块
      }
    },

    // 加载虚拟模块
    load(id) {
      if (id === '\0virtual:my-module') {
        return `export const data = ${JSON.stringify(generateData())}`
      }
    },

    // Vite 特有钩子
    configureServer(server) {
      // 添加自定义中间件
      server.middlewares.use('/custom', (req, res) => {
        res.end('custom response')
      })
    },

    handleHotUpdate({ file, server }) {
      if (file.endsWith('.data')) {
        // 自定义 HMR 处理
        server.ws.send({ type: 'full-reload' })
      }
    }
  }
}

环境变量

bash
# .env                  所有环境
# .env.local            所有环境,本地覆盖(不提交 git)
# .env.development      开发环境
# .env.production       生产环境

VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
# 只有 VITE_ 前缀的变量才会暴露给客户端
ts
// 使用环境变量
const apiUrl = import.meta.env.VITE_API_URL
const isDev = import.meta.env.DEV
const isProd = import.meta.env.PROD
const mode = import.meta.env.MODE  // 'development' | 'production'

// TypeScript 类型声明
/// <reference types="vite/client" />
interface ImportMetaEnv {
  readonly VITE_API_URL: string
  readonly VITE_APP_TITLE: string
}

性能优化技巧

ts
// 1. 预构建优化:手动指定需要预构建的依赖
export default defineConfig({
  optimizeDeps: {
    include: ['lodash-es', 'axios'],  // 强制预构建
    exclude: ['your-local-package']   // 排除预构建
  }
})

// 2. 动态导入(代码分割)
const LazyComponent = lazy(() => import('./LazyComponent'))

// 3. 资源内联阈值
export default defineConfig({
  build: {
    assetsInlineLimit: 4096  // 小于 4KB 的资源内联为 base64
  }
})

// 4. 预加载指令
// Vite 自动为动态导入生成 <link rel="modulepreload">

// 5. 库模式:打包为可发布的库
export default defineConfig({
  build: {
    lib: {
      entry: 'src/index.ts',
      name: 'MyLib',
      formats: ['es', 'cjs', 'umd'],
      fileName: (format) => `my-lib.${format}.js`
    },
    rollupOptions: {
      external: ['vue', 'react'],  // 不打包 peer dependencies
      output: {
        globals: { vue: 'Vue', react: 'React' }
      }
    }
  }
})

总结

  • Vite 开发模式利用原生 ESM,按需转换,无需打包
  • esbuild 预构建 node_modules,比 Webpack 快 10-100 倍
  • HMR 精确到模块级别,修改一个文件只更新该模块
  • 生产构建使用 Rollup,输出优化的静态资源
  • 插件系统兼容 Rollup 插件,生态丰富

系统学习 Web 前端生态,深入底层架构