TYPESCRIPT
#vite#webpack#migration#env#alias#define

Миграция Webpack → Vite: типовые отличия (process.env, алиасы, define)

Практические пары «было (Webpack) / стало (Vite)»: process.env.NODE_ENV → import.meta.env, алиасы, DefinePlugin → define. Только документированный API, минимальный показательный код и выводы по миграции.

Как использовать

  1. Использовать как чеклист при переносе проекта с Webpack на Vite.
  2. Заменить process.env на import.meta.env и переменные в .env на VITE_*; алиасы и define перенести в vite.config.
  3. Проверить: поиск process.env, конфиг алиасов/define, env.d.ts, vite build и vite (dev).

При переносе проекта с Webpack на Vite чаще всего ломаются переменные окружения, алиасы и глобальные константы: в браузере нет process.env, в Vite-конфиге нет __dirname, DefinePlugin заменяется на define. Проблема: «process is not defined», пустые переменные, нерезолвящиеся алиасы. Симптомы: падение приложения в dev/build, неверные значения API URL или режима. Ниже — пары «было / стало» по Vite Env, Vite Config, Webpack DefinePlugin: process.env → import.meta.env, алиасы, DefinePlugin → define; что проверить и типичные ошибки.

Решение

1) process.env.NODE_ENV → import.meta.env

Webpack (было):

if (process.env.NODE_ENV === 'production') { }
const apiBase = process.env.REACT_APP_API_URL ?? '';

Vite (стало):

if (import.meta.env.PROD) { }
const apiBase = import.meta.env.VITE_API_URL ?? '';

В Vite переменные из .env попадают в клиент только с префиксом VITE_. Переименуйте в .env: REACT_APP_API_URLVITE_API_URL. В коде используйте import.meta.env.MODE, DEV, PROD, SSR.

2) Алиасы путей

Webpack (было):

// webpack.config.js
resolve: {
  alias: {
    '@': path.resolve(__dirname, 'src'),
    '@components': path.resolve(__dirname, 'src/components'),
  },
}

Vite (стало):

// vite.config.ts — в ESM нет __dirname
const __dirname = path.dirname(fileURLToPath(import.meta.url));
import path from 'node:path';
import { fileURLToPath } from 'node:url';

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
    },
  },
});

Импорты в коде менять не нужно: import from '@components/Button' остаётся.

3) DefinePlugin → define

Webpack (было):

new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify('production'),
  __APP_VERSION__: JSON.stringify(process.env.npm_package_version || '0.0.0'),
}),

Vite (стало):

define: {
  __APP_VERSION__: JSON.stringify(process.env.npm_package_version || '0.0.0'),
},

Значения передавайте через JSON.stringify. Режим сборки в Vite — через import.meta.env.PROD/DEV, не через define.

Проверка

  1. Поиск по проектуgrep -r "process\.env" src (или аналог). Заменить все вхождения в клиентском коде на import.meta.env; переменные в .env переименовать в VITE_*.

  2. Конфиг — алиасы заданы через path.resolve(__dirname, ...) где __dirname получен из fileURLToPath(import.meta.url). Глобальные константы из DefinePlugin перенесены в define в vite.config.

  3. Типы (TypeScript) — в env.d.ts объявить расширение для Vite:

    /// <reference types="vite/client" />
    interface ImportMetaEnv {
      readonly VITE_API_URL: string;
      // остальные VITE_*
    }
  4. Сборкаpnpm build или vite build. В консоли не должно быть «process is not defined». Откройте собранный бандл и убедитесь, что подставлены нужные значения (например версия, base URL).

  5. Devpnpm dev / vite. Проверить алиасы и переменные окружения в браузере (логи, запросы к API).

Дополнительно: SVG/file-loader — в Vite через плагины (vite-plugin-svgr) или суффиксы ?raw/?url. Публичный путь — base: '/app/' в Vite вместо output.publicPath в Webpack.

Типичные ошибки

  • process.env в клиентском коде — в браузере process нет. Заменить на import.meta.env; кастомные переменные только с префиксом VITE_, иначе не попадут в бандл.
  • __dirname в vite.config — конфиг Vite в ESM; __dirname нет. Использовать path.dirname(fileURLToPath(import.meta.url)).
  • Define без JSON.stringify — в define значения подставляются как есть. Без JSON.stringify подставится идентификатор, а не строка. Правильно: __KEY__: JSON.stringify('value').
  • SVG / raw / file-loader — в Vite нет лоадеров; нужны плагины или суффиксы (?raw, ?url). Иначе импорты SVG/файлов могут падать.
  • publicPath / base — если приложение не в корне домена, в Vite задать base: '/app/'; в Webpack было output.publicPath.

Где применять

  • Миграция существующего фронта с Webpack на Vite: пошаговая замена env, алиасов, define и проверка сборки и dev. Продакшн после успешного build и тестов.
  • Новые проекты: сразу использовать Vite production-конфиг. Сравнение с Webpack — Webpack production-конфиг.

Связанные сниппеты: Vite: production-конфиг 2026, Webpack: production-конфиг 2026.