Vite 配置优化

工程化   2025-06-01 10:45   25   0  

vite.config.ts

import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv, ConfigEnv, UserConfig } from 'vite'
import { getVitePlugins } from './build/plugins'
import { getBuildConfig } from './build/build'

export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
  // 加载环境变量
  const env = loadEnv(mode, process.cwd())
  // 当前执行 node 命令时文件夹的地址 工作目录
  const root = process.cwd()

  return {
    root: root,
    // 插件
    plugins: getVitePlugins(mode),

    // 别名配置
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url)),
      },
    },

    // 服务器配置
    server: {
      port: Number(env.VITE_API_BASE_PORT),
      host: '0.0.0.0',
      open: false,
      proxy: env.VITE_USE_PROXY === 'true' ? {
        [env.VITE_PROXY_URL]: {
          target: env.VITE_API_BASE_URL,
          changeOrigin: true,
          rewrite: (path) => path.replace(new RegExp(`^${env.VITE_APP_PROXY_URL}`), '')
        }
      } : undefined
    },

    // 构建配置
    build: getBuildConfig(mode),

    // 预构建优化大型依赖加载性能
    optimizeDeps: {
      // 强制预构建的依赖
      include: ['lodash-es', 'axios', 'element-plus'],
      // 排除的依赖
      exclude: []
    },

    // CSS 预处理器配置
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@use "@/styles/variables.scss" as *;',
          // 暂时禁用即将被废弃的 API 警告
          silenceDeprecations: ["legacy-js-api"],
        }
      }
    }
  }
})

项目根目录下创建 build 文件夹 -> 用于配置打包、插件

build.ts
import { fileURLToPath, URL } from 'node:url'
import { loadEnv } from 'vite'
import type { PreRenderedAsset } from 'rollup'

export const getBuildConfig = (mode: string) => {
  const env = loadEnv(mode, process.cwd())

  return {
    // 输出目录
    outDir: 'dist',
    // 静态资源目录
    assetsDir: 'assets',
    // 生成 sourcemap
    sourcemap: false,
    // 代码压缩方式
    minify: 'esbuild' as const,
    // 构建目标
    target: 'es2015',
    // 禁用压缩大小报告
    reportCompressedSize: false,
    // CSS代码分割
    cssCodeSplit: true,
    // 构建时清空输出目录
    emptyOutDir: true,
    // 构建时监听文件变化
    watch: mode === 'development' ? {
      include: ['src/**'],
      exclude: ['node_modules/**', 'dist/**']
    } : null,
    // 资源内联大小限制 4kb
    assetsInlineLimit: 4096,
    // 配置打包压缩选项
    esbuild: {
      // 移除 console debugger
      drop: env.VITE_DROP_CONSOLE_DEBUGGER === 'true' ? ['console', 'debugger'] : [],
      // 移除注释
      legalComments: 'none',
      // 压缩配置
      minifyIdentifiers: true,
      minifySyntax: true,
      minifyWhitespace: true,
      // 目标环境
      target: 'es2015',
    },
    // 块大小警告阈值 KB
    chunkSizeWarningLimit: 2048,
    // 环境变量处理
    define: {
      // 在代码中获取当前环境 console.log(__APP_ENV__)
      __APP_ENV__: JSON.stringify(env.APP_ENV),
      // 生产环境可以使用传统的 Options API 写法
      __VUE_OPTIONS_API__: true,
      // 在生产环境禁用 Vue DevTools
      __VUE_PROD_DEVTOOLS__: false,
      // 控制是否在生产环境显示水合 hydration 不匹配的详细信息
      __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false
    },
    // CSS 处理配置
    css: {
      // CSS Modules 配置
      modules: {
        localsConvention: 'camelCase',
        scopeBehavior: 'local',
        generateScopedName: '[name]_[local]_[hash:base64:5]'
      }
    },
    // 代码分割配置
    rollupOptions: {
      input: {
        main: fileURLToPath(new URL('../index.html', import.meta.url))
      },
      output: {
        // 单独打包
        manualChunks: {
          // UI库
          'element-plus': ['element-plus'],
          // 状态管理
          'pinia': ['pinia'],
          // 路由
          'vue-router': ['vue-router'],
          // 工具库
          'utils': ['lodash-es', 'axios'],
          // 核心框架
          'vue': ['vue']
        },
        // 入口文件命名规则
        entryFileNames: 'assets/js/[name].[hash].js',
        // 代码分割后的文件命名规则
        chunkFileNames: 'assets/js/[name].[hash].js',
        // 打包目录结构优化 按照 img、js、css、other 进行分组
        assetFileNames: (assetInfo: PreRenderedAsset) => {
          if (!assetInfo.name) return 'assets/other/[name].[hash][extname]'
          // 获取文件名和扩展名
          const fileName = assetInfo.name
          const ext = fileName.split('.').pop()?.toLowerCase()
          // 根据文件类型分类
          if (ext === 'svg' || ['png', 'jpg', 'jpeg', 'gif', 'webp', 'ico'].includes(ext || '')) {idea上方怎么添加当前代码处于哪个分支idea上方怎么添加当前代码处于哪个分支
            return 'assets/img/[name].[hash][extname]'
          } else if (['css', 'scss', 'sass', 'less'].includes(ext || '')) {
            return 'assets/css/[name].[hash][extname]'
          } else {
            return 'assets/other/[name].[hash][extname]'
          }
        }
      }
    }
  }
}
plugins.ts
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import vueDevTools from 'vite-plugin-vue-devtools'
import { loadEnv } from 'vite'

export const getVitePlugins = (mode: string) => {
  const env = loadEnv(mode, process.cwd())

  return [
    vue(),
    vueJsx(),
    env.VITE_USE_DEVTOOLS === 'true' && vueDevTools()
  ].filter(Boolean)
}

配合 .env

.env.development
# 开发环境配置
VITE_APP_ENV=development

# 开发环境标题
VITE_APP_TITLE=Web Project Base (Dev)

# 开发环境服务接口
VITE_API_BASE_URL=http://192.168.2.127

# 开发环境端口
VITE_API_BASE_PORT=20000

# 开发环境超时配置
VITE_APP_API_TIMEOUT=15000

# 开发环境是否启用调试工具
VITE_USE_DEVTOOLS=true

# 开发环境是否启用代理
VITE_USE_PROXY=true

# 开发环境代理地址
VITE_PROXY_URL=/api

# 开发环境是否删除 console.log debugger
VITE_DROP_CONSOLE_DEBUGGER=false
.env.production
# 生产环境配置
VITE_APP_ENV=production

# 生产环境标题
VITE_APP_TITLE=Web Project Base

# 生产环境服务接口
VITE_API_BASE_URL=http://192.168.2.127

# 生产环境端口
VITE_API_BASE_PORT=20000

# 生产环境超时配置
VITE_APP_API_TIMEOUT=15000

# 生产环境是否启用调试工具
VITE_USE_DEVTOOLS=false

# 生产环境是否启用代理
VITE_USE_PROXY=false

# 生产环境代理地址
VITE_PROXY_URL=/api

# 生产环境是否删除 console.log debugger
VITE_DROP_CONSOLE_DEBUGGER=true
.env.test
# 测试环境配置
VITE_APP_ENV=test

# 测试环境标题
VITE_APP_TITLE=Web Project Base (Test)

# 测试环境服务接口
VITE_API_BASE_URL=http://192.168.2.127

# 测试环境端口
VITE_API_BASE_PORT=20000

# 测试环境超时配置
VITE_APP_API_TIMEOUT=15000

# 测试环境是否启用调试工具
VITE_USE_DEVTOOLS=false

# 测试环境是否启用代理
VITE_USE_PROXY=false

# 测试环境代理地址
VITE_PROXY_URL=/api

# 测试环境是否删除 console.log debugger
VITE_DROP_CONSOLE_DEBUGGER=true

打包结果展示:

10422_qxg1_3548.png