AgentSkillsCN

vite-config

为React单体仓库构建配置Vite的模式。当您需要配置构建过程、解决打包问题,或优化输出结果时,可优先选用此技能。

SKILL.md
--- frontmatter
name: vite-config
description: Vite configuration patterns for React monorepo builds. Use when configuring builds, fixing bundling issues, or optimizing output.
license: MIT

Vite Configuration

When to Use

Activate when:

  • Configuring new package builds
  • Fixing "multiple React instances" errors
  • Optimizing bundle size
  • Adding code splitting
  • Debugging build issues

Project Vite Configs

PackageConfigPlugin
webglvite.config.jsreact-swc
chatvite.config.jsreact-swc
header-auth-linksvite.config.jsreact-swc
testingvite.config.jsreact-swc ✅ (best config)
websitevite.config.jsreact (standard)

Standard Config Template

Use this for all packages:

javascript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import path from 'path';
import { fileURLToPath } from 'url';
import pkg from './package.json';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const rootDir = path.resolve(__dirname, '../..');

export default defineConfig({
  plugins: [react()],

  base: './',

  resolve: {
    alias: {
      // Force single React instance
      react: path.resolve(rootDir, 'node_modules/react'),
      'react-dom': path.resolve(rootDir, 'node_modules/react-dom'),
      'react/jsx-runtime': path.resolve(rootDir, 'node_modules/react/jsx-runtime'),
      'react/jsx-dev-runtime': path.resolve(rootDir, 'node_modules/react/jsx-dev-runtime'),
      // Shared package alias
      '@disruptive-spaces/shared': path.resolve(rootDir, 'packages/shared'),
    },
    dedupe: ['react', 'react-dom', 'framer-motion', '@chakra-ui/react', '@emotion/react'],
  },

  optimizeDeps: {
    include: ['react', 'react-dom', 'react/jsx-runtime'],
    force: true,
  },

  build: {
    outDir: 'dist',
    emptyOutDir: true,
    sourcemap: true,
    rollupOptions: {
      output: {
        entryFileNames: `assets/main.v${pkg.version}.js`,
        chunkFileNames: `assets/[name].v${pkg.version}.js`,
        assetFileNames: `assets/[name].v${pkg.version}.[ext]`,
      },
    },
  },
});

React Deduplication (Critical)

Why It's Needed

Without deduplication:

  • Each package bundles its own React
  • Hooks fail with "Invalid hook call"
  • Context doesn't work across package boundaries
  • useState, useEffect break silently

Full Solution

javascript
resolve: {
  alias: {
    // All React paths point to root node_modules
    'react': path.resolve(rootDir, 'node_modules/react'),
    'react-dom': path.resolve(rootDir, 'node_modules/react-dom'),
    'react/jsx-runtime': path.resolve(rootDir, 'node_modules/react/jsx-runtime'),
    'react/jsx-dev-runtime': path.resolve(rootDir, 'node_modules/react/jsx-dev-runtime'),
  },
  dedupe: ['react', 'react-dom', 'framer-motion', '@chakra-ui/react'],
},

optimizeDeps: {
  include: ['react', 'react-dom', 'react/jsx-runtime'],
  force: true,  // Rebuild on every dev start
},

Code Splitting

javascript
build: {
  rollupOptions: {
    output: {
      manualChunks: {
        // Vendor chunks
        'vendor-react': ['react', 'react-dom'],
        'vendor-chakra': ['@chakra-ui/react', '@emotion/react', 'framer-motion'],
        'vendor-agora': ['agora-rtc-sdk-ng', 'agora-rtc-react'],
        'vendor-firebase': ['firebase/app', 'firebase/firestore', 'firebase/auth'],
      },
    },
  },
},

Library Mode (for shared packages)

javascript
// packages/shared/vite.config.js
export default defineConfig({
  build: {
    lib: {
      entry: path.resolve(__dirname, 'index.js'),
      name: 'DisruptiveShared',
      formats: ['es', 'cjs'],
      fileName: (format) => `index.${format}.js`,
    },
    rollupOptions: {
      external: ['react', 'react-dom', 'firebase'],
    },
  },
});

Environment Variables

javascript
// vite.config.js
export default defineConfig({
  define: {
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
  },

  envPrefix: ['VITE_', 'REACT_APP_'], // Expose these to client
});

Access in code:

javascript
const apiKey = import.meta.env.VITE_API_KEY;

Plugin: React SWC vs Babel

Featurereact-swcreact (Babel)
Speed~20x fasterSlower
ConfigMinimalExtensive
PluginsLimitedFull Babel ecosystem
Recommendation✅ Use thisOnly if need Babel plugins
javascript
// Prefer this
import react from '@vitejs/plugin-react-swc';

// Only use if you need Babel plugins
import react from '@vitejs/plugin-react';

Debugging Builds

bash
# Analyze bundle
pnpm add -D rollup-plugin-visualizer

# In vite.config.js
import { visualizer } from 'rollup-plugin-visualizer';

plugins: [
  react(),
  visualizer({ open: true }),
],

Common Issues

IssueCauseFix
Multiple ReactMissing dedupeAdd resolve.alias + dedupe
Hooks errorReact not dedupedCheck alias paths are correct
Missing stylesCSS not extractedAdd cssCodeSplit: true
Large bundleNo code splittingAdd manualChunks
Slow HMRLarge depsAdd to optimizeDeps.include

Files to Update

When applying this config:

  1. packages/webgl/vite.config.js
  2. packages/chat/vite.config.js
  3. packages/header-auth-links/vite.config.js
  4. packages/website/vite.config.js

(testing package already has the best config - use as reference)

Related Skills

  • monorepo-deps - Dependency management
  • frontend-development - React patterns