Vite

Зачем нужно

Vite — современный инструмент сборки от создателя Vue (Evan You). Vite кардинально быстрее Webpack в dev-режиме благодаря нативным ES-модулям браузера: вместо пересборки всего бандла при каждом изменении, Vite отдаёт файлы как есть, а браузер сам разрешает импорты. Production-сборка использует Rollup.

Где используется

  • Разработка SPA на React, Vue, Svelte, Solid
  • TypeScript-проекты (встроенная поддержка)
  • Библиотеки (library mode)
  • SSR-приложения (Nuxt, SvelteKit используют Vite)

Почему Vite быстрее

Webpack (Bundle-based dev server)

Изменение файла
      ↓
Webpack пересобирает бандл (секунды/минуты)
      ↓
Весь бандл отправляется в браузер
      ↓
Страница обновляется

Vite (Native ESM dev server)

Изменение файла
      ↓
Vite обновляет ТОЛЬКО этот файл (миллисекунды)
      ↓
Браузер запрашивает модуль по HTTP
      ↓
HMR обновляет компонент без перезагрузки
Webpack:  Все модули → Бандл → Браузер
          [1000 модулей → 1 файл]
          Время: O(n) от размера проекта

Vite:     Браузер → Запрашивает модуль → Vite трансформирует → Отдаёт
          [По требованию, только нужные файлы]
          Время: O(1) — не зависит от размера проекта

Pre-bundling зависимостей

Vite использует esbuild (Go, невероятно быстрый) для pre-bundling node_modules:

node_modules/lodash-es/ (600+ файлов)
      ↓ esbuild (10-100x быстрее Webpack)
.vite/deps/lodash-es.js (1 файл)

Быстрый старт

# Создание проекта
npm create vite@latest my-app -- --template vanilla
npm create vite@latest my-app -- --template react
npm create vite@latest my-app -- --template react-ts
npm create vite@latest my-app -- --template vue
npm create vite@latest my-app -- --template svelte

cd my-app
npm install
npm run dev
Структура проекта:
my-app/
├── index.html          ← Точка входа (не в src!)
├── src/
│   ├── main.js         ← JS точка входа
│   └── style.css
├── public/             ← Статические файлы (копируются as-is)
├── vite.config.js      ← Конфигурация
└── package.json

Конфигурация

// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  // Плагины
  plugins: [react],

  // Dev server
  server: {
    port: 3000,
    open: true,            // Открыть браузер
    proxy: {
      // /api/* → http://localhost:4000/api/*
      '/api': {
        target: 'http://localhost:4000',
        changeOrigin: true,
      },
    },
  },

  // Production build
  build: {
    outDir: 'dist',
    sourcemap: true,
    minify: 'terser',     // или 'esbuild' (быстрее)
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
        },
      },
    },
  },

  // Resolve
  resolve: {
    alias: {
      '@': '/src',
      '@components': '/src/components',
    },
  },

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

  // Переменные окружения
  define: {
    __APP_VERSION__: JSON.stringify('1.0.0'),
  },
});

Переменные окружения

# .env
VITE_API_URL=http://localhost:4000
VITE_APP_TITLE=My App

# .env.production
VITE_API_URL=https://api.example.com

# .env.development
VITE_API_URL=http://localhost:4000
// В коде — только переменные с префиксом VITE_
console.log(import.meta.env.VITE_API_URL);
console.log(import.meta.env.MODE);  // 'development' | 'production'
console.log(import.meta.env.DEV);   // true в dev
console.log(import.meta.env.PROD);  // true в prod

Встроенные возможности (без плагинов)

// TypeScript — работает из коробки
import { greet } from './utils.ts';

// CSS Modules — .module.css
import styles from './App.module.css';

// SCSS/SASS — нужен только sass (npm install -D sass)
import './styles.scss';

// JSON
import data from './data.json';

// Статические ресурсы
import logo from './logo.png';     // URL
import raw from './shader.glsl?raw'; // Содержимое как строка

// Web Workers
const worker = new Worker(
  new URL('./worker.js', import.meta.url),
  { type: 'module' }
);

Плагины Vite

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import legacy from '@vitejs/plugin-legacy';
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  plugins: [
    // React с Fast Refresh
    react,

    // Поддержка старых браузеров
    legacy({
      targets: ['defaults', 'not IE 11'],
    }),

    // Аналог BundleAnalyzer
    visualizer({
      open: true,
      filename: 'stats.html',
    }),
  ],
});

Свой плагин

// Плагин Vite — объект с хуками
function myPlugin() {
  return {
    name: 'my-plugin',

    // Трансформация модулей
    transform(code, id) {
      if (id.endsWith('.md')) {
        return `export default ${JSON.stringify(code)}`;
      }
    },

    // Конфигурация dev server
    configureServer(server) {
      server.middlewares.use('/health', (req, res) => {
        res.end('OK');
      });
    },
  };
}

Code Splitting

// Динамический import — автоматический chunk
const About = () => import('./pages/About.vue');
const Dashboard = () => import('./pages/Dashboard.vue');

// Manual chunks в конфиге
build: {
  rollupOptions: {
    output: {
      manualChunks(id) {
        if (id.includes('node_modules')) {
          // Каждая крупная зависимость — отдельный chunk
          if (id.includes('react')) return 'react-vendor';
          if (id.includes('lodash')) return 'lodash';
          return 'vendor';
        }
      },
    },
  },
},

Миграция с Webpack на Vite

Шаг 1: index.html → корень проекта (не src/)
Шаг 2: Добавить <script type="module" src="/src/main.js"> в HTML
Шаг 3: Заменить require → import
Шаг 4: process.env → import.meta.env
Шаг 5: Webpack-специфичные фичи → Vite-плагины
// Webpack → Vite: основные замены

// require → import
// const fs = require('fs')        →  import fs from 'fs'
// require('./style.css')          →  import './style.css'

// process.env → import.meta.env
// process.env.NODE_ENV            →  import.meta.env.MODE
// process.env.REACT_APP_*        →  import.meta.env.VITE_*

// Webpack-specific
// require.context                 →  import.meta.glob
// module.hot                      →  import.meta.hot
// import.meta.glob — замена require.context
const modules = import.meta.glob('./pages/*.js');
// { './pages/Home.js':  => import('./pages/Home.js'), ... }

// Eager loading
const modules = import.meta.glob('./pages/*.js', { eager: true });
// { './pages/Home.js': { default: ... }, ... }

Частые ошибки

  1. index.html в src/ — Vite ожидает index.html в корне проекта
  2. process.env вместо import.meta.env — process.env не определён в Vite
  3. Нет префикса VITE_ — переменные без VITE_ не попадают в клиентский код (безопасность)
  4. CommonJS в кодеrequire не работает, нужен import
  5. Тяжёлые зависимости не pre-bundled — добавить в optimizeDeps.include вручную
  6. HMR не работает — файл не экспортирует компоненты или нет плагина фреймворка

Практика

  1. Создать Vite-проект с npm create vite@latest
  2. Настроить алиасы (@/src/), proxy для API
  3. Подключить SCSS и CSS Modules
  4. Настроить переменные окружения (.env, .env.production)
  5. Проанализировать бандл с rollup-plugin-visualizer
  6. Мигрировать маленький Webpack-проект на Vite

Связанные темы

Ресурсы