Миграция React-приложений с webpack на Vite
Миграция React-приложений на Vite может заметно ускорить локальную сборку, но сначала стоит проверить разрывы в плагинах, изменения в настройке тестов и случаи, когда webpack всё ещё подходит лучше.

Почему webpack начинает тормозить в старых React-приложениях
Старые React-приложения редко замедляются из-за одного неудачного решения. Обычно они тормозят потому, что за годы сборка успевает обрасти правилами, лоадерами, алиасами, полифиллами и разовыми исправлениями. Каждое дополнение когда-то было оправдано. Вместе они превращают обычный запуск dev server в долгую паузу.
Эта пауза особенно заметна в повседневной работе. Вы меняете одну кнопку, одну подпись в форме или маленький стиль, а webpack часто делает больше, чем того требует правка. Ему приходится проходить большой граф зависимостей, запускать преобразования и поддерживать старые слои совместимости. Небольшое изменение интерфейса начинает казаться дорогим, когда приложение уже переросло свою исходную настройку.
Конфиг со временем становится ещё и командным долгом. Новые сотрудники открывают файлы сборки, видят несколько плагинов, цепочки кастомных лоадеров и правила для разных окружений — и решают не трогать ничего без крайней необходимости. Это важно. Когда менять сборку безопасно только одному-двум людям, каждое обновление занимает больше времени, а мелкие проблемы месяцами остаются без внимания.
Есть и ещё одна проблема: расхождение между разработкой и продакшеном. В старой webpack-настройке часто появляются отдельные пути для локальной работы и релизной сборки. Где-то CSS ведёт себя чуть иначе, ассеты получают другие имена, или плагин запускается только в одном режиме. Приложение продолжает работать, но сюрпризы появляются в самый неудобный момент — прямо перед релизом, а не во время разработки.
Это часто бывает в командах стартапов и малого и среднего бизнеса, с которыми работает Олег Сотников. Приложение ещё работает, но сборка начинает ощущаться тяжелее самого продукта. Обычно именно тогда миграция React-приложений на Vite становится практичным разговором, а не просто модным трендом.
Что меняется в ежедневной работе
Разница заметна уже в первый день. Vite запускает dev server без предварительной полной сборки приложения, поэтому рабочий экран появляется гораздо быстрее. В старых webpack-проектах даже небольшое изменение может означать ожидание полной пересборки, прежде чем можно будет продолжить работу.
Эта скорость особенно важна в обычной работе с React. Когда кто-то меняет подпись в форме, поправляет отступы или исправляет ошибку состояния в одном компоненте, браузер обновляется почти сразу. Задержка в 10 или 15 секунд звучит не так уж страшно, но если это происходит весь день, она сбивает фокус и делает мелкие задачи тяжелее, чем они есть на самом деле.
У большинства React-команд при этом становится меньше конфигурации. Vite закрывает типовые сценарии с меньшим количеством деталей, поэтому часто удаётся убрать старые правила лоадеров, кастомные настройки dev server и лишние плагины, которые копились годами. Для проекта, который несколько раз переходил из рук в руки, такая зачистка иногда не менее полезна, чем сама прибавка в скорости.
В ежедневной работе обычно меняются несколько вещей:
- разработчики меньше ждут, когда запускают приложение утром
- правки интерфейса и CSS обновляются гораздо быстрее
- проще разобраться в локальной сборке
- ошибки в браузере чаще указывают прямо на код приложения
- небольшие задачи по фронтенду легче закрывать за один заход
Простой пример помогает это увидеть. Представьте внутреннюю панель с 40 страницами, общими компонентами и большим webpack-конфигом, который никто не хочет трогать. На webpack изменение одной панели фильтров может означать медленную пересборку и сомнения, загрузилось ли изменение вообще. На Vite та же правка обычно появляется достаточно быстро, чтобы разработчик не выпадал из потока.
Но не стоит оценивать миграцию только по локальной скорости. Сравнивайте и продакшен-результат. Проверьте размер бандла, загрузку маршрутов, кеширование, source maps и то, как собранное приложение ведёт себя в вашей реальной схеме деплоя. Быстрое обновление локально — это отлично, но миграция React-приложений на Vite окупается только тогда, когда продакшен остаётся стабильным и предсказуемым.
Проверьте приложение до миграции
С гладкой миграции React-приложений на Vite нужно начинать не с переписывания конфига, а с инвентаризации. Команды обычно сталкиваются с проблемами, когда приложение зависит от мелких webpack-правил, к которым годами никто не прикасался.
Запишите каждый лоадер, плагин, алиас и кастомный скрипт, который использует текущая сборка. Сюда входят скрипты сборки в package.json, webpack-алиасы вроде @components и любой плагин, который меняет импорты, добавляет глобальные переменные или переписывает файлы во время сборки.
Отдельно стоит проверить работу с ассетами. SVG часто становятся первым сюрпризом. Одно приложение импортирует их как URL, другое использует как React-компоненты, а третье делает и то и другое. Проверьте и CSS modules, особенно если у вас есть свой шаблон именования классов. То же самое сделайте для изображений, шрифтов и всего, что загружается из public folder.
Короткий список поможет не пропустить важное:
- отметьте, как сегодня работают импорты SVG, изображений и шрифтов
- проверьте, используют ли CSS modules и Sass нестандартные имена или глобальные стили
- перечислите тестовые инструменты, mock-настройки, env vars и правила локального proxy
- найдите код браузера, который всё ещё ждёт Node API вроде
path,fs,processилиBuffer
Тесты часто ломаются раньше, чем само приложение. Если вы используете Jest, webpack-алиасы, setup-файлы или file mocks, для этого нужен совместимый с Vite вариант. Env vars тоже меняют форму. Код, который читает process.env, может потребовать правок, а правила локального API proxy должны соответствовать тому, как команда реально разрабатывает приложение, а не только тому, как оно работает в продакшене.
Скрытые проблемы часто приходят от пакетов, которые ожидают browser environment, похожую на Node. Старые библиотеки могут без предупреждения обращаться к Buffer или process. Панель может выглядеть нормально, пока не откроется одна страница отчёта, где такой пакет ломается только в режиме разработки.
Если сначала разложить все эти детали по полочкам, переход на Vite становится куда менее драматичным. Вы перестаёте гадать и точно знаете, какие части приложения нужно доработать до того, как кто-то переключит сборку по умолчанию.
Сначала перенесите одну ветку
Миграция React-приложений на Vite проходит лучше, если воспринимать её как эксперимент, а не как переписывание. Откройте небольшую ветку, перенесите одну точку входа приложения и не раздувайте объём работ. Оставьте основную webpack-настройку в покое, пока ветка не сможет запускаться, собираться и показывать несколько обычных экранов без сюрпризов.
Добавьте Vite и React-плагин рядом с текущими скриптами, а не вместо них в первый же день. Оставьте webpack-команды, которыми команда уже пользуется. Затем добавьте отдельные Vite-команды для локальной разработки и production build. Так у вас появится чистое сравнение бок о бок, а не рискованный одномоментный переход.
Большинство проблем всплывает в связке, а не в самих React-компонентах. Сначала перенесите path aliases. Затем переведите env vars на формат Vite и проверьте все места, где приложение читает изображения, шрифты или SVG. Внутренняя панель может отлично работать в webpack, но быстро сломаться в Vite, если один импорт зависит от старого правила лоадера или скрытой ссылки на process.env.
Маленькой миграционной ветке обычно нужны такие проверки:
- приложение запускается без ошибок импорта или алиасов
- локальные env values загружаются в режиме разработки
- статические ассеты находятся по ожидаемым путям
- production build завершается, и результат выглядит нормально
После этого попросите одного коллегу поработать в этой ветке день или два. Не давайте ему заготовленный демо-сценарий. Пусть он откроет страницы, с которыми работает каждую неделю, поменяет компонент, запустит сборку и запишет все шероховатости. Такой тест быстро ловит раздражающие мелочи: чувствительные к регистру импорты, странное поведение CSS или плагин, который незаметно работал только потому, что webpack это позволял.
Перед тем как что-то объединять, сравните Vite build и webpack build на одном и том же коммите. Если оба варианта собирают одно и то же приложение, а Vite ощущается быстрее в повседневной работе, у вас есть крепкая основа для следующего шага.
Где всплывают разрывы в плагинах
Большая часть боли при миграции — не в React. Она в маленьких webpack-плагинах и лоадерах, которые годами формировали приложение. Если какая-то функция работает только потому, что webpack переписывает файлы во время сборки, вам нужен Vite-плагин, другой пакет или небольшое изменение в коде приложения.
Начните с файлов, которые не являются обычным JavaScript или CSS. Чаще всего первым ломается SVG. Один экран может импортировать SVG как URL, а другой ожидать React-компонент. Markdown-файлы могут ломаться по той же причине, а для скриптов воркеров часто нужен новый синтаксис импорта.
Короткая проверка обычно быстро показывает самые рискованные места:
- нестандартные SVG-импорты
- markdown- или MDX-файлы
- веб-воркеры или service workers
- настройка Module Federation
- плагины, которые глубоко вмешиваются во внутренности webpack
Module Federation требует особой осторожности. Vite может закрывать похожие сценарии, но многие webpack-настройки remote и host не переносятся напрямую. Если ваше приложение зависит от кастомных правил sharing, проверок версии во время работы или плагинов, которые патчат webpack compiler, закладывайте ручную работу, а не простой swap один к одному.
Старые цепочки лоадеров — ещё один частый камень преткновения. В webpack-конфиге файл может проходить через два или три лоадера, прежде чем React его увидит. Vite обычно предпочитает более простой путь. Иногда это значит один плагин. Иногда — перенос логики прямо в приложение, что позже часто проще поддерживать.
Некоторые плагины лучше убрать, а не переносить. Vite уже решает многие задачи, для которых старые webpack-проекты ставили дополнительные пакеты. Если плагин нужен был только для ускорения обновления, базовых импортов ассетов или неудобных настроек по умолчанию, сначала проверьте приложение без него. Если тащить в Vite все старые плагины, работы станет больше, а реальные разрывы будет сложнее увидеть.
Тесты, env vars и ассеты требуют отдельного внимания
Приложение на React может выглядеть отлично после миграции на Vite, а потом сломаться в мелочах, которые отнимают полдня. Чаще всего такие проблемы связаны с тестами, env vars и работой с ассетами, а не с самим React.
Сначала обычно нужно привести в порядок env vars. Код, который читает process.env.REACT_APP_API_URL, в Vite не будет работать так же. Обычно такие значения переименовывают с префиксом VITE_ и читают через import.meta.env. Это заодно заставляет сделать полезную проверку: если значение доступно в браузере, считайте его публичным. Команды часто находят старые переменные, которым вообще не следовало попадать в клиентский код.
На тесты тоже стоит посмотреть внимательно. Если вы переходите с Jest на Vitest, setup-файлы, mocks и globals часто требуют небольших правок. Файл вроде setupTests.js может остаться, но раннер загружает его иначе. Вызовы jest.mock часто заменяются на vi.mock, а некоторым хелперам, которые опирались на Jest globals, нужны явные импорты. Это не сложно, но мелкие отличия быстро накапливаются.
Короткая проверка обычно ловит большую часть проблем:
- переименуйте переменные
REACT_APP_и замените чтение черезprocess.env - убедитесь, что файл настройки тестов запускается перед каждым набором тестов
- проверьте mock-модули, таймеры и поведение
fetch - сравните output CSS modules, PostCSS и Sass на реальных страницах
- откройте экраны со шрифтами, изображениями, SVG и динамическими импортами
Ассеты заслуживают полноценной проверки в браузере, а не только зелёной сборки. CSS modules могут немного иначе хэшировать имена. Плагины PostCSS могут загрузиться в другом порядке, если конфиг настроен не так. Для шрифтов и изображений могут понадобиться правки путей, особенно если раньше их обслуживали webpack-алиасы или file loaders.
Если на одной странице есть lazy imports, кастомные шрифты и Sass, откройте именно её первой. Она обычно быстрее всего показывает самые неприятные места.
Простой пример на внутренней панели
Миграцию React-приложений на Vite проще представить на примере небольшой внутренней панели продаж. В приложении сотрудники редактируют сделки, фильтруют большие таблицы, смотрят графики выручки и импортируют CSV-файлы от партнёров. С бэкендом всё было в порядке. Боль жила в локальной разработке.
На webpack команда каждый раз ждала, когда начинала работу. Dev server сначала разбирал почти весь фронтенд, даже если человеку нужно было поменять только одно поле формы или один столбец таблицы. На старых ноутбуках запуск переваливал за минуту. Небольшая правка в компоненте графика могла вызвать ещё одну долгую паузу.
Они перенесли одно React-приложение на Vite в отдельной ветке и оставили API, auth и код базы данных как есть. Это снизило риск. Приложение по-прежнему общалось с тем же бэкендом и использовало те же контракты данных. Основная работа пришлась на frontend build setup, обработку env и несколько проверок пакетов.
Результат стал заметен уже в первый день. Разработчики открывали приложение быстрее и получали почти мгновенные reloads при работе с формами, таблицами и графиками. На настроение это повлияло сильнее, чем любая таблица с бенчмарками. Когда человек может исправить баг в фильтре за 10 секунд вместо ожидания нескольких пересборок, он пробует больше идей и замечает больше мелких ошибок.
Одна часть всё же сломалась: поток импорта CSV. Старый webpack-настройка зависела от плагина, который после перехода работал неудачно. Вместо того чтобы чинить это сложным патчем, команда заменила его на более простой CSV parser и обновила экран импорта. Это заняло дополнительное время, но заодно убрало старую зависимость, которую никто не хотел поддерживать.
Такой переход лучше всего работает, когда у приложения есть чёткая граница. Если React-фронтенд можно перенести, не таща за собой бэкенд, команда быстро увидит выигрыш в скорости и успеет исправить несколько шероховатостей до того, как все переключатся.
Ошибки, которые тормозят миграцию
Команды обычно теряют время, когда воспринимают миграцию как уборку, а не как управляемое изменение. Самая большая ошибка — переносить сразу все приложения в репозитории. Если ломается общий пакет, скрипт сборки или правило env, никто не понимает, где началась проблема.
Безопаснее сначала перенести одну ветку или одно приложение. Выберите что-то реальное, но не самый хрупкий продукт в репозитории. Небольшая внутренняя панель часто лучше, чем основное клиентское приложение, потому что команду проще тестировать быстро и понять, что меняет Vite в повседневной работе.
Ещё одна частая ошибка — считать, что у каждого webpack-плагина есть прямой аналог в Vite. У некоторых он есть. У некоторых — нет. А некоторые проблемы вообще больше не требуют плагина, потому что Vite решает их проще. Команды тратят дни на поиски идеальной замены, хотя стоило бы остановиться и спросить: "А нам вообще всё ещё нужно это поведение?"
Проблемы в продакшене тоже часто всплывают слишком поздно, если никто не проверяет output до последней недели. В режиме разработки всё может выглядеть отлично, а в реальной сборке всё ещё будут сломанные пути к ассетам, слишком большие чанки или env values, которые загружаются иначе. Проверяйте production build заранее и продолжайте проверять его по ходу работы.
Ещё несколько ошибок повторяются снова и снова:
- команда забывает про правила поддержки браузеров и отправляет слишком современный output старым пользователям
- никто не проверяет версию Node, которая нужна Vite, и локальные окружения начинают расходиться
- старые webpack-файлы остаются в репозитории, и люди только гадают, какой скрипт реально запускается
- CI продолжает использовать старые команды, даже после изменений в локальной разработке
Именно здесь миграция React-приложений на Vite может застопориться по причинам, которые никак не связаны с самим Vite. Большинство задержек возникает из-за смешанных сигналов, оставшегося конфига и слишком большого числа движущихся частей одновременно. Удаляйте то, чем больше не пользуетесь, понятно называйте скрипты и тестируйте production build до того, как команда окончательно полюбит более быстрый dev server.
Быстрые проверки перед тем, как команда переключится
Команде не стоит переключаться только потому, что Vite кажется быстрее на одном ноутбуке. Передача безопасна только тогда, когда приложение работает одинаково для всех — на чистой установке и в production.
Попросите одного разработчика, который не работал над миграционной веткой, клонировать репозиторий, установить зависимости и запустить dev server. Этот простой тест быстро выявляет многое: отсутствующие env-файлы, path aliases, которые работают только на одной машине, и скрипты, завязанные на старое поведение webpack.
Перед переключением проверьте пять вещей:
- свежий клон запускает dev server без ручных исправлений
- production build завершается без ошибок
- пути к ассетам продолжают работать после деплоя, включая шрифты, изображения и лениво загружаемые чанки
- тесты покрывают экраны, которые команда правит каждую неделю
- старый путь релиза через webpack по-прежнему остаётся доступным
Именно в production становятся видны мелкие ошибки. Откройте собранное приложение в staging-среде и пройдитесь по маршрутам, которыми люди пользуются каждый день. Проверьте вложенные маршруты, публичные URL ассетов и любое приложение, которое живёт в подкаталоге, потому что именно здесь миграции с webpack на Vite чаще всего идут не так.
Сделайте ещё один скучный тест: сломайте приложение специально. Спровоцируйте ошибку во фронтенде и убедитесь, что система отслеживания ошибок её получает. Потом откройте stack trace и проверьте, что source maps указывают на реальный файл и строку. Если этот шаг не проходит, первый же production-баг отнимет часы.
Для отката нужен реальный план, а не обещание. Оставьте последнюю webpack-сборку готовой на первый релизный период и заранее решите, кто сможет вернуть трафик назад, если появится что-то странное. Если откат занимает 10 минут, команда намного спокойнее выпускает миграцию.
Когда имеет смысл остаться на webpack
Переход на Vite часто оправдан, но не каждое React-приложение нужно переводить сразу. Если webpack и так подходит приложению, принудительная миграция может съесть время, не решив реальную проблему.
Самая очевидная причина остаться — сложная логика сборки. Некоторые старые приложения зависят от кастомных лоадеров, которые переписывают импорты, патчат legacy-пакеты, добавляют feature flags или преобразуют файлы в очень строгом порядке. Если такое поведение накапливалось годами и никто не хочет трогать его перед релизом, webpack может оставаться более безопасным вариантом.
Module Federation — ещё один частый стоп-сигнал. Если ваше приложение выступает host для нескольких remote, или другие команды зависят от текущей federation-настройки, заменить этот слой сборки редко получается быстро. Мигрировать можно и позже, но слишком ранний переход может сломать работу за пределами вашей команды.
Не менее важен и момент. Если команда заморожена перед релизом, готовится к аудиту или в этом квартале закрывает контрактный дедлайн, смена инструмента добавляет риск. Даже плавная миграция React-приложений на Vite всё равно меняет обработку env, настройку тестов и поведение ассетов.
Иногда цифры просто не оправдывают работу. Если локальный запуск занимает 10–15 секунд, production build завершается за пару минут, а разработчики не упираются в проблемы каждый день, то, возможно, сначала стоит заняться чем-то другим. Нестабильные тесты или мёртвый код могут дать больше пользы, чем смена bundler.
Хорошее правило простое: оставайтесь на webpack, когда он защищает то, что бизнесу нужно прямо сейчас. Переходите, когда медленные сборки, плохой поток разработки или сложность сборки действительно отнимают у команды время каждую неделю.
Что делать дальше
Начните с цифр. Если команде кажется, что webpack работает медленно, измерьте три вещи в текущем приложении: холодный старт, время обновления после небольшой правки компонента и время production build. Эти цифры помогут честно обсудить Vite и позже покажут, окупился ли переход.
Не начинайте с самого загруженного приложения в компании. Выберите одно приложение с низким риском или один пакет, который не блокирует продажи, поддержку или биллинг. Небольшой внутренний инструмент часто лучше, чем основное клиентское приложение, потому что команда быстрее тестирует изменения и проще откатывается назад.
Прежде чем кто-то назовёт дату, запишите все места, где webpack до сих пор делает особую работу. Обычно это кастомные лоадеры, алиасы, обработка SVG, environment variables и необычное поведение плагинов. Короткий список разрывов лучше, чем оптимизм. Если список маленький, переход может пройти быстро. Если список всё растёт, partial migration может быть более разумным решением.
Практичный план выглядит так:
- зафиксируйте текущие времена запуска, обновления и сборки
- перенесите одно приложение или пакет с низким риском в отдельной ветке
- перечислите разрывы в плагинах и проверьте их по одному
- сравните новую сборку со старой перед тем, как переключать команду
Если перед решением вам нужен внешний взгляд, Олег Сотников может оценить вашу React-сборку, риск миграции и то, имеет ли смысл небольшой переход на Vite. Это особенно помогает, когда в приложении много кастомного поведения и никто не хочет сюрпризов прямо перед релизом.
Для многих команд миграция React-приложений на Vite лучше всего работает как управляемый эксперимент, а не как большое переписывание. Одна ветка, одна цель, понятные цифры. Так вы быстро получите реальный ответ.