Миграция с Create React App

### Причины перехода с Create React App на Vite Create React App (CRA) долгое время использовался как стандартный инструмент для создания React-приложений без ручной настройки сборки. Однако по мере роста проектов и усложнения фронтенд-экосистемы стали проявляться ограничения архитектуры CRA: медленный старт dev-сервера, перегруженная конфигурация, зависимость от Webpack и сложность кастомизации без eject. Vite предлагает иной подход к разработке: использование нативных ES-модулей в dev-режиме и сборки на базе Rollup. Это радикально ускоряет запуск проекта и обновление модулей при изменениях кода. Ключевые различия, влияющие на миграцию: * CRA использует Webpack и bundling на старте * Vite использует ESM и подгружает модули по требованию * горячая перезагрузка в Vite работает точечно на уровне модулей * конфигурация Vite намеренно минималистична и расширяется через плагины --- ### Архитектурные различия, влияющие на миграцию Переход с CRA на Vite нельзя рассматривать как простую замену инструмента сборки. Меняется сама модель обработки приложения. В CRA входная точка всегда скрыта внутри `react-scripts`, тогда как в Vite она явно задаётся через `index.html`, который становится частью графа зависимостей. Особенности Vite: * `index.html` находится в корне проекта * скрипт подключения приложения указывается явно * обработка ассетов идёт через import-механику * dev-server не бандлит весь проект заранее В CRA: * HTML генерируется внутри build pipeline * конфигурация скрыта внутри `react-scripts` * расширение поведения требует eject или CRACO --- ### Подготовка проекта к миграции Перед переходом важно провести инвентаризацию CRA-проекта: * кастомные webpack-конфиги (если есть eject или CRACO) * переменные окружения `.env` * алиасы импортов * обработка SVG и статических ресурсов * proxy настройки API * тестовый стек (Jest) Типичный CRA-проект содержит: ``` src/ public/ package.json .env ``` В Vite структура сохраняется, но добавляется: ``` vite.config.js index.html (в корне) ``` --- ### Установка Vite и базовая конфигурация Замена CRA на Vite начинается с удаления зависимостей `react-scripts` и установки Vite: ```bash npm install vite @vitejs/plugin-react ``` Далее создаётся конфигурационный файл: ```js // vite.config.js import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()] }) ``` Плагин `@vitejs/plugin-react` заменяет функциональность Babel внутри CRA: JSX трансформация, Fast Refresh и поддержка React Refresh runtime. --- ### Перенос entry point и index.html В CRA входной файл скрыт в `src/index.js`. В Vite он остаётся, но подключается иначе. Было (CRA): ```js ReactDOM.createRoot(document.getElementById('root')).render() ``` Структура HTML скрыта. Стало (Vite): ```html
``` Изменение принципиальное: браузер напрямую загружает модуль. --- ### Переменные окружения В CRA переменные окружения начинаются с `REACT_APP_`, в Vite — с `VITE_`. Пример миграции: CRA: ``` REACT_APP_API_URL=https://api.example.com ``` Vite: ``` VITE_API_URL=https://api.example.com ``` Использование: ```js const apiUrl = import.meta.env.VITE_API_URL ``` Важно учитывать, что `process.env` в Vite не используется напрямую. --- ### Алиасы и структура импортов CRA часто использует `jsconfig.json` или `tsconfig.json` для алиасов, либо CRACO для webpack alias. Vite поддерживает алиасы через `resolve.alias`: ```js import { defineConfig } from 'vite' import path from 'path' export default defineConfig({ resolve: { alias: { '@': path.resolve(__dirname, './src') } } }) ``` После миграции все импорты вида: ```js import Button from '@/components/Button' ``` остаются без изменений при корректной настройке. --- ### Работа со статическими файлами В CRA папка `public` используется для статических ресурсов без обработки bundler’ом. В Vite логика похожа, но есть важные отличия: * файлы из `public` доступны напрямую через `/` * импорт файлов из `src` проходит через систему модулей Пример: ```js import logo from './assets/logo.png' ``` или: ```html ``` Файл из `public/logo.png`. --- ### CSS и препроцессоры Vite поддерживает CSS из коробки без дополнительной настройки: * CSS Modules * SCSS * PostCSS SCSS: ```bash npm install sass ``` Использование: ```js import './styles.scss' ``` CSS Modules: ```css .button { color: red; } ``` ```js import styles from './Button.module.css' ``` --- ### Proxy и работа с API В CRA proxy настраивается через `package.json`: ```json "proxy": "http://localhost:5000" ``` В Vite используется конфигурация server: ```js export default defineConfig({ server: { proxy: { '/api': { target: 'http://localhost:5000', changeOrigin: true } } } }) ``` --- ### Замена Jest и тестовой инфраструктуры CRA включает Jest по умолчанию. В Vite он не встроен, что требует выбора альтернатив: * Vitest * Jest с ручной настройкой Рекомендуемый вариант — Vitest: ```bash npm install vitest ``` Конфигурация: ```js export default defineConfig({ test: { environment: 'jsdom' } }) ``` Преимущества: * совместимость с Vite pipeline * быстрый запуск * поддержка ESM --- ### Обработка SVG и ассетов В CRA SVG часто импортируются как ReactComponent: ```js import { ReactComponent as Icon } from './icon.svg' ``` В Vite для этого используется плагин: ```bash npm install vite-plugin-svgr ``` Конфигурация: ```js import svgr from 'vite-plugin-svgr' export default defineConfig({ plugins: [react(), svgr()] }) ``` Использование: ```js import Icon from './icon.svg?react' ``` --- ### Оптимизация сборки CRA использует Webpack production build, Vite — Rollup. Особенности Vite build: * tree-shaking по умолчанию * code splitting автоматически * поддержка dynamic imports Команда сборки: ```bash vite build ``` Результат помещается в `dist/`. --- ### Изменения в поведении HMR Hot Module Replacement в Vite работает на уровне ES модулей: * обновляются только изменённые модули * состояние компонентов сохраняется чаще * нет полного перезапуска дерева зависимостей В CRA HMR завязан на Webpack runtime, что делает обновления более тяжёлыми. --- ### Типовые проблемы миграции #### Использование process.env Код: ```js process.env.REACT_APP_API ``` Должен быть заменён на: ```js import.meta.env.VITE_API ``` --- #### Конфликты CommonJS Vite ориентирован на ESM. Некоторые зависимости требуют: * динамического импорта * или оптимизации через `optimizeDeps` --- #### Абсолютные импорты При неправильной настройке alias возникают ошибки резолва модулей. --- #### SSR-особенности библиотек Некоторые пакеты, рассчитанные на CRA/Webpack, могут ломаться из-за различий в окружении Vite. --- ### Настройка TypeScript в Vite Vite поддерживает TS без компиляции через tsc в dev-режиме. Базовая конфигурация: ```json { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["src/*"] } } } ``` --- ### Итоговая структура после миграции ``` project/ index.html vite.config.js src/ main.jsx App.jsx assets/ public/ package.json ``` --- ### Переключение скриптов package.json Было (CRA): ```json "scripts": { "start": "react-scripts start", "build": "react-scripts build" } ``` Стало (Vite): ```json "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" } ```