Vue.js: Vite Configuration

Last updated: 2026-10-20

Vite is the next-generation build tool from the Vue 3 team, with a cold start 30x faster than Webpack. Vite 5/6 brings major improvements to TypeScript, SSR, and build optimization, and is the standard choice for modern Vue projects.

This lesson walks you through a complete Vite 5/6 engineering setup: vite.config.ts, path aliases, env variables, SCSS, auto-imports, and build optimization. These are essential skills for enterprise Vue projects.

1. What You'll Learn


2. A "5-Minute Cold Start" Developer Experience Comparison

(1) Pain Point: Webpack Takes 30 Seconds to Cold Start, Developers Give Up Waiting

Alice's team used Webpack:

BASH
# Webpack project cold start
$ npm run dev
> Project is running at http://localhost:8080
> Compiled successfully in 28.5s  ← 30 seconds of waiting

Team lead Charlie:

"Alice, the dev server takes 30 seconds to start. Every file save costs 3 seconds of hot reload. We need to switch to Vite."

(2) The Vite Fix: 5-Second Cold Start, Millisecond HMR

BASH
# Vite project cold start
$ npm run dev
> VITE v5.4.0  ready in 487 ms  ← only 0.5 seconds
> Local: http://localhost:5173/

Developer experience comparison:

Operation Webpack 5 Vite 5
Cold start 28s 0.5s
HMR 1-3s < 50ms
Build (large project) 30-60s 5-15s

A 56x faster cold start. After switching to Vite, development speed improves dramatically.

(3) Benefits

After moving to Vite:


3. Vite 5/6 Core Concepts

(1) Vite's Two Modes

TEXT
Development mode (dev):
  - Uses native ESM; the browser imports modules directly
  - Compiles on demand (a module is compiled on first access)
  - Extremely fast HMR (only the changed module is updated)

Production mode (build):
  - Bundles with Rollup
  - Automatic tree-shaking / code splitting / minification
  - Outputs to the dist/ directory

(2) 5 Core Advantages

Advantage Description
Instant cold start esbuild pre-bundles dependencies (written in Go, 100x faster than JS-based babel)
Compile on demand Only compiles the modules currently accessed, not the whole project
Native ESM The browser loads modules directly via <script type="module">
Blazing-fast HMR Changing 1 file updates only that 1 module
SSR / SSG First-class support (officially recommended by Nuxt 3)

(3) Vite 5/6 vs Vite 4

Dimension Vite 4 Vite 5/6
Startup speed Fast Faster (better dependency pre-bundling)
Build speed 5-15s 3-8s
Node requirement 14+ 18+
Rollup 3.x 4.x
ESM by default ✅ ✅
Recommendation Legacy ⭐⭐⭐⭐⭐

4. The Complete vite.config.ts

(1) Basic Structure

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

export default defineConfig({
  // Project root (defaults to process.cwd())
  root: '.',
  
  // Base public path
  base: '/',
  
  // Plugins
  plugins: [vue()],
  
  // Dev server
  server: {
    port: 5173,
    open: true,  // open the browser automatically
    host: '0.0.0.0'  // reachable on the LAN
  },
  
  // Build
  build: {
    outDir: 'dist',
    sourcemap: false,
    minify: 'esbuild'
  },
  
  // CSS
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/variables.scss";`
      }
    }
  },
  
  // Path aliases
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  }
})

(2) 5 Core Config Sections

TS
export default defineConfig({
  // 1. Path aliases (the most used)
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@stores': path.resolve(__dirname, 'src/stores')
    }
  },
  
  // 2. Dev server
  server: {
    port: 5173,
    open: true,
    host: '0.0.0.0',
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true
      }
    }
  },
  
  // 3. CSS preprocessors
  css: {
    preprocessorOptions: {
      scss: { /* ... */ },
      less: { /* ... */ }
    }
  },
  
  // 4. Build optimization
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          'vue-vendor': ['vue', 'vue-router', 'pinia']
        }
      }
    },
    chunkSizeWarningLimit: 1500
  },
  
  // 5. Dependency optimization
  optimizeDeps: {
    include: ['vue', 'vue-router', 'pinia']
  }
})

5. 3 Kinds of Environment Variables

(1) The VITE_ Prefix Rule

BASH
# .env.development
VITE_API_BASE_URL=http://localhost:3000
VITE_APP_TITLE=My App (Dev)

# .env.production
VITE_API_BASE_URL=https://api.example.com
VITE_APP_TITLE=My App

# .env.local (git-ignored, one per developer)
VITE_API_KEY=secret-key

(2) TypeScript Declarations

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

interface ImportMetaEnv {
  readonly VITE_API_BASE_URL: string
  readonly VITE_APP_TITLE: string
  readonly VITE_API_KEY?: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

(3) Using Them in Components

TS
const apiUrl = import.meta.env.VITE_API_BASE_URL
const title = import.meta.env.VITE_APP_TITLE

(4) Priority of the 4 .env Files

File Purpose Git
.env Shared by all environments Commit
.env.development Development only Commit
.env.production Production only Commit
.env.local Local overrides (not committed) Ignore

▶ Example: Environment Variable Injection + Conditional Rendering (browser-runnable)

💡 This is a browser-runnable equivalent demo: Vite statically replaces import.meta.env with literals at build time, so a plain constant object simulates that injection and a mode switch flips between the dev and prod values.

▶ Try it Yourself

Output:

TEXT
First render: title is My App (Dev), API base is http://localhost:3000, and "🛠 Dev build: debug panel visible (HMR connected)" is shown.
After clicking "Switch build mode": the title becomes My App, the API base becomes https://api.example.com, the debug panel disappears and the prod message appears.
Same as real Vite: values are replaced by literals at build time, and the dev branch of the v-if is dropped entirely from the production bundle.

▶ Example: 3 Environment Variable Configurations

BASH
# .env.development (development)
VITE_API_BASE_URL=http://localhost:3000

# .env.production (production)
VITE_API_BASE_URL=https://api.example.com

# .env.local (local, not committed to Git)
VITE_API_KEY=secret
TS
// src/env.d.ts (TypeScript declarations)
interface ImportMetaEnv {
  readonly VITE_API_BASE_URL: string
  readonly VITE_API_KEY?: string
}
TS
// Use it in .vue / .ts files
const apiUrl = import.meta.env.VITE_API_BASE_URL

Output:

TEXT
With npm run dev the value of apiUrl is http://localhost:3000;
with npm run build it is https://api.example.com.
Variables without the VITE_ prefix (and values from .env.local when it exists) are replaced during the build, and Volar offers autocompletion for both keys through src/env.d.ts.
TEXT
dev   → import.meta.env.VITE_API_BASE_URL === 'http://localhost:3000'
build → import.meta.env.VITE_API_BASE_URL === 'https://api.example.com'
.env.local overrides both when present (regardless of mode)

6. SCSS Integration

(1) Installation

BASH
npm install -D sass

(2) Global Variables

SCSS
// src/styles/variables.scss
$primary: #42b883;
$danger: #ef4444;
$font-size-base: 14px;
$border-radius: 4px;
TS
// vite.config.ts
css: {
  preprocessorOptions: {
    scss: {
      // Injected into every .scss file automatically
      additionalData: `@import "@/styles/variables.scss";`
    }
  }
}
SCSS
// Usable directly in any .scss file
.button {
  background: $primary;  /* no @import needed */
  color: white;
  border-radius: $border-radius;
}

(3) 5 SCSS Advantages


7. Auto-Imports with unplugin-auto-import

(1) Installation

BASH
npm install -D unplugin-auto-import

(2) Configuration

TS
// vite.config.ts
import AutoImport from 'unplugin-auto-import'

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      imports: ['vue', 'vue-router', 'pinia'],
      dts: 'src/auto-imports.d.ts',  // type declarations
      eslintrc: {
        enabled: true  // generates .eslintrc-auto-import.json
      }
    })
  ]
})

(3) Usage

VUE
<script setup>
// ✅ No more import of ref / computed / watch
const count = ref(0)
const double = computed(() => count.value * 2)
watch(count, (val) => console.log(val))

// ✅ No more useRouter import
const router = useRouter()
</script>

(4) 5 Advantages

Advantage Description
Fewer imports No need to write import ref / computed every time
Type safety The dts file generates types automatically
Configurable Choose exactly which APIs are auto-imported
ESLint friendly Generates the .eslintrc file to suppress import warnings
Fast builds Does not slow down bundling

8. 5 Build Optimizations

(1) Code Splitting (manualChunks)

TS
// vite.config.ts
build: {
  rollupOptions: {
    output: {
      manualChunks: {
        'vue-vendor': ['vue', 'vue-router', 'pinia'],
        'echarts-vendor': ['echarts', 'vue-echarts'],
        'utils': ['axios', 'dayjs']
      }
    }
  }
}

(2) Tree-shaking (on by default)

TS
build: {
  rollupOptions: {
    treeshake: {
      moduleSideEffects: 'no-external',  // treat all modules as side-effect free
      propertyReadSideEffects: false     // treat property reads as side-effect free
    }
  }
}

(3) CSS Minification

TS
build: {
  cssMinify: 'lightningcss',  // 10x faster than esbuild
  // or 'esbuild' (the default)
}

(4) Asset Handling

TS
build: {
  assetsInlineLimit: 4096,  // assets < 4KB are inlined (base64)
  rollupOptions: {
    output: {
      assetFileNames: 'assets/[name]-[hash][extname]',
      chunkFileNames: 'js/[name]-[hash].js',
      entryFileNames: 'js/[name]-[hash].js'
    }
  }
}

(5) Source Maps (debugging in production)

TS
build: {
  sourcemap: true,  // generate them in production too (for Sentry)
  rollupOptions: {
    output: {
      sourcemapExcludeSources: true  // do not inline the source into the map
    }
  }
}

9. Putting It Together: One Config for Dev and Build

▶ Example: A Complete vite.config.ts (⚠️ requires a Vite project)

⚠️ The code below belongs in vite.config.ts; the CDN global build does not apply. It demonstrates the core options:

TS
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import'
import path from 'path'

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      imports: ['vue', 'vue-router', 'pinia'],
      dts: 'src/auto-imports.d.ts'
    })
  ],

  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')   // @ → src/
    }
  },

  server: {
    port: 5173, open: true,                 // open the browser on start
    proxy: {
      '/api': {
        target: 'http://localhost:3000',    // proxy forwarding
        changeOrigin: true
      }
    }
  },

  css: {
    preprocessorOptions: {
      scss: {
        additionalData: '@import "@/styles/variables.scss";'
      }
    }
  },

  build: {
    outDir: 'dist', sourcemap: true,
    rollupOptions: {
      output: {
        manualChunks: { 'vue-vendor': ['vue', 'vue-router', 'pinia'] }
      }
    }
  }
})
▶ Try it Yourself

Output:

TEXT
No page is rendered; this is a build-time config file.
When you run npm run dev, Vite prints VITE v5.x.x ready in ...
ms plus Local: http://localhost:5173/, the browser opens automatically, @/...
imports resolve to src/..., requests to /api/* are forwarded to http://localhost:3000, and npm run build writes hashed bundles plus source maps into dist/.
TEXT
$ npm run dev
  VITE v5.4.0  ready in 487 ms
  ➜  Local:   http://localhost:5173/
  ➜  Network: http://192.168.1.10:5173/
  [proxy] /api/products → http://localhost:3000/api/products

$ npm run build
  dist/index.html
  dist/assets/index-8f3a1c.css
  dist/js/vue-vendor-2b7d9e.js
  dist/js/index-4c1a06.js
  dist/js/index-4c1a06.js.map

(1) 📊 5 Build Optimizations

Optimization Config
Code splitting rollupOptions.output.manualChunks
Tree-shaking build.treeshake settings
CSS minification build.cssMinify: 'lightningcss'
Asset handling build.assetsInlineLimit + file name patterns
Source Maps build.sourcemap: true

(2) 📊 Quick Reference for 5 Common Mistakes

Mistake Symptom Fix
Path alias not working Imports fail Use path.resolve with __dirname
SCSS variable undefined Compile error Auto-import it via additionalData
Env variable is undefined undefined at runtime Use the VITE_ prefix + .env files
auto-import not working ref cannot be found Check that the dts file was generated
White screen in production Wrong paths Set base: '/yourpath/'

(3) 📊 5 Vite Performance Comparisons

Configuration Cold start HMR Production build
Default 0.5s 50ms 10s
+ alias 0.5s 50ms 10s
+ SCSS 0.6s 60ms 11s
+ auto-import 0.6s 60ms 11s
+ manualChunks 0.6s 60ms 12s (but 50% faster first paint)

❓ FAQ

Q What is the minimum Node version for Vite 5/6?
A Node 18+ (since October 2023). Node 16 is EOL. Vite 4 still supports Node 14+.
Q How do I use __dirname with path.resolve in ESM?
A Use import.meta.url: fileURLToPath(new URL('./src', import.meta.url)). Vite 5 recommends combining resolve.alias with path.resolve.
Q Is the VITE_ prefix on env variables mandatory?
A Yes. For security reasons Vite only exposes variables with the VITE_ prefix. Everything else is not bundled.
Q Does auto-import work in production?
A Yes. unplugin-auto-import removes the auto-import code during build (turning it into explicit imports), so it does not affect the bundle.
Q Vite or Webpack?
A Always Vite for new projects. Webpack is only for maintaining legacy projects. Vite's cold start is 30x faster and HMR 60x faster.
Q How do I configure Vite SSR?
A Use vite build --ssr or the Nuxt 3 integration. SSR configuration is a bit involved (you have to handle hydration), but Vite's official support is solid.
Q When is the dts file of unplugin-auto-import generated?
A When the dev server starts and during build. You can also generate it manually with npx auto-imports.

📖 Summary


📝 Exercises

  1. Basic (difficulty ⭐) Create a Vite + Vue 3 project and configure:

    • The path alias @ → src
    • Global SCSS variables
    • A .env.development containing VITE_API_BASE_URL
  2. Intermediate (difficulty ⭐⭐) A complete Vite configuration:

    • Path aliases (@ / @components / @stores)
    • SCSS + auto-imported variables
    • unplugin-auto-import (vue + vue-router + pinia)
    • Proxy /api to the backend
    • manualChunks for the production build (vue-vendor)
  3. Challenge (difficulty ⭐⭐⭐) Build a complete "enterprise-grade Vite configuration":

    1. 5 path aliases (@ / @components / @stores / @utils / @composables)
    2. Global SCSS variables + 5 mixins (flex / card / button / form / responsive)
    3. unplugin-auto-import + Volar type generation
    4. 3 environments (dev / staging / prod)
    5. 5 build optimizations (manualChunks / tree-shaking / lightningcss / assets / sourcemap)
    6. Proxy /api to the backend
    7. A complete TypeScript setup (env.d.ts + auto-imports.d.ts)
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏