Типичные проблемы при миграции
Миграция с Webpack, Vue CLI, Create React App или Parcel на Vite почти всегда сопровождается набором повторяющихся проблем, связанных не столько с самим Vite, сколько с различиями в архитектуре сборки, модели модулей и способе обработки ассетов. Большая часть ошибок проявляется не сразу, а на этапе сборки production или при переходе от привычной конфигурации к ESM-ориентированной модели.
### Переход на ESM и отказ от CommonJS
Одной из ключевых причин сбоев становится переход Vite на нативные ES-модули в разработке. Старые проекты часто активно используют `require`, `module.exports` и смешанные импорты.
Типичные проявления проблемы:
* ошибки вида `require is not defined`
* невозможность загрузки некоторых библиотек в dev-режиме
* несовместимость с CJS-only пакетами
Vite частично решает это через pre-bundling зависимостей с помощью esbuild, однако остаются случаи, когда:
* библиотека не имеет ESM-сборки
* экспорт реализован нестандартно
* используется динамический `require`
Решения обычно сводятся к:
* явному указанию оптимизации зависимостей через `optimizeDeps`
* замене импортов на ESM-совместимые версии библиотек
* использовании `createRequire` в редких Node-специфичных случаях
### Различия в работе с переменными окружения
В старых сборщиках широко используется `process.env`. В Vite модель принципиально иная: доступ к окружению осуществляется через `import.meta.env`.
Проблемы миграции:
* `process is not defined` в браузере
* переменные не подхватываются в рантайме
* различия между dev и build окружением
Особенности Vite:
* переменные должны начинаться с префикса `VITE_`
* доступ только через `import.meta.env.VITE_*`
* разные режимы (`development`, `production`, кастомные mode)
Часто требуется массовая замена:
* `process.env.API_URL` → `import.meta.env.VITE_API_URL`
### Обработка статических ассетов
В Webpack и Vue CLI существует привычная модель загрузчиков (`file-loader`, `url-loader`). Vite использует иную стратегию: ассеты обрабатываются как ESM-импорты.
Типичные проблемы:
* некорректные пути к изображениям
* поломка динамических URL
* различия между `public` и `src/assets`
Особенности:
* всё внутри `src` обрабатывается через import graph
* папка `public` копируется без трансформации
* доступ к ассетам через `new URL('./img.png', import.meta.url)`
Частая ошибка — использование строковых путей:
* `img: "/assets/logo.png"` может работать в dev, но ломаться в build при изменении `base`
### Проблемы с base path и деплоем
Vite строго разделяет базовый путь приложения через параметр `base`.
Типовые ошибки:
* приложение работает локально, но ломается на проде
* неверные пути к JS и CSS чанкам
* 404 на статические файлы
Причины:
* отсутствие настройки `base` при деплое в подкаталог
* ожидание поведения Webpack publicPath
Решение обычно связано с явным указанием:
* `base: '/app/'` для подкаталога
* или `base: './'` для относительной раздачи
### Различия dev-сервера и production-сборки
Vite использует dev-сервер на основе native ESM, а production — через Rollup.
Проблемы:
* поведение кода отличается между dev и build
* динамические импорты работают в dev, но ломаются в build
* плагины ведут себя по-разному
Особенно часто встречается:
* ошибки code splitting
* отсутствие чанков в production
* некорректная загрузка lazy routes
Причина в том, что:
* dev использует on-demand трансформацию
* build строит статический граф модулей
### Конфликты с алиасами и резолвингом путей
В старых проектах часто используется `@` или кастомные алиасы через Webpack.
Типичные проблемы:
* алиасы не распознаются
* TypeScript понимает пути, а Vite нет
* различия между dev и IDE
В Vite требуется явная настройка:
* `resolve.alias` в `vite.config.js`
Также часто возникает рассинхронизация:
* `tsconfig.json` paths
* Vite alias
* Jest alias (если используется)
### Проблемы с CSS и препроцессорами
Vite поддерживает CSS нативно, но поведение отличается от Webpack pipeline.
Частые проблемы:
* Sass переменные не подхватываются глобально
* порядок подключения стилей меняется
* CSS Modules ведут себя иначе
Особенности:
* каждый `.vue` или `.module.css` обрабатывается изолированно
* глобальные стили нужно подключать явно
* PostCSS конфигурация должна быть вынесена корректно
### Ошибки при работе с динамическими импортами
Vite строго анализирует `import()` выражения.
Проблемы:
* динамические пути вида `import(path)` не работают
* требуется статическая часть пути
* Webpack-подобные конструкции ломаются
Пример проблемного кода:
* `import(\`./views/${name}.vue`)`
В Vite требуется:
* `import.meta.glob`
* или явное перечисление модулей
### import.meta.glob и различие с Webpack context
Webpack использует `require.context`, тогда как Vite предлагает `import.meta.glob`.
Типичные проблемы:
* отсутствие привычного API
* неправильное использование glob-паттернов
* неожиданный формат возвращаемых модулей
Особенность Vite:
* результат — объект функций импорта
* требуется дополнительная обработка `.then(m => m.default)`
### Проблемы с Node.js polyfills
Vite не предоставляет автоматические polyfills для Node встроенных модулей.
Ошибки:
* `Buffer is not defined`
* `process is not defined`
* `path`, `crypto`, `stream` отсутствуют
Причина:
* Vite ориентирован на браузер
* Webpack раньше часто включал polyfills по умолчанию
Решения:
* явное подключение polyfill-библиотек
* настройка `resolve.alias` для Node модулей
* отказ от Node-зависимых библиотек в фронтенде
### Конфликты с зависимостями и optimizeDeps
Vite заранее предсобирает зависимости через esbuild.
Проблемы:
* зависимость не обновляется после изменения
* stale cache приводит к странным багам
* некоторые пакеты игнорируются prebundle
Симптомы:
* изменения в node_modules не отражаются
* ошибка оптимизации зависимостей
Решения:
* очистка `node_modules/.vite`
* настройка `optimizeDeps.include/exclude`
### Проблемы с legacy-браузерами
Vite по умолчанию ориентирован на современные браузеры.
Ошибки:
* отсутствие поддержки IE11
* некорректная работа старых Safari
* отсутствие транспиляции без плагина legacy
Причина:
* минимизация transpilation overhead
* использование native ESM
Для старых окружений требуется:
* `@vitejs/plugin-legacy`
### Несовместимость плагинов Webpack
Одна из самых частых проблем — попытка перенести Webpack loader напрямую.
Ошибки:
* `style-loader`, `file-loader` не работают
* Babel loader конфигурации теряют смысл
* плагины SSR требуют переписывания
В Vite используется:
* plugin-based архитектура Rollup
* специфические Vite-плагины вместо loader-цепочек
### Проблемы с HMR
Hot Module Replacement в Vite работает иначе, чем в Webpack.
Типичные проблемы:
* состояние компонента сбрасывается
* обновления приходят не туда
* HMR не срабатывает при глубокой вложенности
Причина:
* иной механизм инвалидации модулей
* более агрессивный dependency graph
### Monorepo и workspace сложности
В монорепозиториях часто возникают проблемы с резолвингом зависимостей.
Симптомы:
* дублирование пакетов
* ошибки при импорте локальных библиотек
* некорректный pre-bundling
Причины:
* Vite не всегда корректно резолвит hoisted dependencies
* необходимость ручной настройки `server.fs.allow`
### Различия в сборке чанков
Rollup внутри Vite генерирует другую структуру чанков, чем Webpack.
Проблемы:
* изменённые имена файлов
* нестабильный hash
* неожиданный split vendor-кода
Это влияет на:
* кеширование
* CDN стратегии
* интеграцию с backend шаблонами
### Проблемы с proxy и dev API
Dev-сервер Vite требует явной настройки proxy.
Ошибки:
* CORS в development
* запросы идут не на backend
* различия между dev и prod endpoints
Причина:
* Vite не навязывает backend интеграцию
* proxy конфиг заменяет Webpack devServer proxy
### Итоговая картина миграционных проблем
Основные сложности при переходе на Vite формируются вокруг трёх направлений: переход на ESM-модель, изменение pipeline обработки ассетов и различие между dev и production архитектурами. Большинство ошибок не связано с самим Vite, а является следствием удаления скрытых абстракций, которые раньше предоставлял Webpack и его экосистема loaders/plugins.