📚 现代前端开发 目录
阶段2:工程化
第 10 / 35 课

构建工具:Vite

极速开发体验的秘密

📖 核心概念

💻 代码实现

Vite配置实战 ✅ javascript
// vite.config.ts
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';
import { visualizer } from 'rollup-plugin-visualizer';
import { compression } from 'vite-plugin-compression';

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

  return {
    plugins: [
      react(),
      svgr(),
      compression({ algorithm: 'gzip' }),
      mode === 'analyze' && visualizer({ open: true }),
    ].filter(Boolean),

    resolve: {
      alias: {
        '@': '/src',
        '@components': '/src/components',
        '@hooks': '/src/hooks',
        '@stores': '/src/stores',
        '@utils': '/src/utils',
      },
    },

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

    server: {
      port: 3000,
      open: true,
      proxy: {
        '/api': {
          target: env.VITE_API_URL,
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, ''),
        },
      },
    },

    build: {
      target: 'es2020',
      outDir: 'dist',
      sourcemap: mode === 'development',
      minify: 'terser',
      terserOptions: {
        compress: { drop_console: mode === 'production' },
      },
      rollupOptions: {
        output: {
          manualChunks: (id) => {
            if (id.includes('node_modules')) {
              if (id.includes('react')) return 'react-vendor';
              if (id.includes('lodash')) return 'lodash-vendor';
              return 'vendor';
            }
          },
          chunkFileNames: 'js/[name]-[hash].js',
          assetFileNames: (info) => {
            const ext = info.name.split('.').pop();
            const map = { css: 'css', svg: 'images', png: 'images' };
            return \`\${map[ext] || 'assets'}/[name]-[hash].[ext]\`;
          },
        },
      },
    },

    optimizeDeps: {
      include: ['react', 'react-dom', 'react-router-dom'],
    },
  };
});
自定义Vite插件 ✅ javascript
// 自定义Vite插件:自动生成路由
function autoRoutesPlugin(options = {}) {
  const { dir = 'src/pages', prefix = '' } = options;
  const virtualModuleId = 'virtual:auto-routes';
  const resolvedId = '\0' + virtualModuleId;

  return {
    name: 'vite-plugin-auto-routes',
    resolveId(id) {
      if (id === virtualModuleId) return resolvedId;
    },
    async load(id) {
      if (id !== resolvedId) return;

      // 扫描pages目录生成路由
      const pages = await globby(dir);
      const routes = pages
        .filter(f => f.endsWith('.tsx'))
        .map(file => {
          const path = file
            .replace(dir, '')
            .replace('/index.tsx', '')
            .replace('.tsx', '')
            .replace(/\[([^\]]+)\]/g, ':$1')
            || '/';
          return { path: prefix + path, component: file };
        });

      return \`export const routes = \${JSON.stringify(routes, null, 2)}\`;
    },
  };
}

// 环境变量类型安全
// src/env.d.ts
interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly VITE_APP_TITLE: string;
  readonly VITE_ENABLE_ANALYTICS: string;
}
interface ImportMeta {
  readonly env: ImportMetaEnv;
}

// .env.development
// VITE_API_URL=http://localhost:3001
// VITE_APP_TITLE=开发环境

// .env.production
// VITE_API_URL=https://api.example.com
// VITE_APP_TITLE=生产环境

🔍 Vite开发技巧

Vite的开发服务器基于原生ESM,首次启动极快。但首次访问页面时需要预编译依赖,可能稍慢。使用optimizeDeps.include预声明常用依赖可以加速。生产构建使用Rollup,支持Tree Shaking和代码分割。常见问题:CJS依赖需要预编译、Glob导入动态路径、SSR兼容性。

🎯 练习任务

🏆 成就解锁
构建配置师 — 掌握Vite配置与插件开发,打造极速开发体验