Админка, настройки, логин, кабинеты преподавателя и студента полностью переведены на React 19 (модель strangler, docs/REACT_MIGRATION.md). - 15 вкладок админки: lazy-загрузка, общий error boundary, сервисный слой - Удалены legacy-views и переходный слой LegacyTabView (45 файлов) - Сборка esbuild (frontend/scripts/build-react.mjs) с бюджетами gzip на чанки - CSP-хэши, кэширование: chunk'и immutable, CSS/HTML no-cache (react-cache.conf) - Фиксы: lazy-импорт именованных экспортов (краш после авторизации), растяжение #admin-root/#settings-root на всю ширину, возврат subjects/lessonTypes из справочников (краш просмотра расписаний), отказ от заведомо широкого поиска расписания без выбранной цели, центрирование карточки логина - Тесты: 237/237 (npm run check), регрессионные на lazy-вкладки и ширину - Документация: REACT_MIGRATION.md, REACT_MIGRATION_RESULT.md, FRONTEND.md
6.4 KiB
Итоги миграции frontend на React
Дата завершения: 28.09.2026. Полный журнал процесса — в REACT_MIGRATION.md,
архитектура итогового решения — в FRONTEND.md.
Что сделано
По модели strangler (этапы 1–5, все изменения не закоммичены — коммит по решению владельца):
| Этап | Содержимое | Статус |
|---|---|---|
| 1. Точка входа и вход в систему | index.html, страница логина |
Завершён |
| 2. Интерфейс студента | SPA student/ |
Завершён |
| 3. Интерфейс преподавателя | SPA teacher/ (пожелания, заявки) |
Завершён |
| 4. Страница настроек | Отдельный SPA admin/settings/ (4 вкладки) |
Завершён |
| 5. Основная админ-панель | Shell + hash-router + 15 вкладок в 6 волнах | Завершён |
Волны этапа 5: dashboard, classrooms, subjects → users, groups, university-structure →
teacher-requests, department-workspace → auditorium-workload, academic-calendar →
schedule-view, schedule-versions, schedule-quality, teacher-absences → schedule
(конструктор правил + абсорбция панели разовых правок).
Удалено 45 legacy-файлов (~19 000 строк vanilla-кода): все admin/js/views/*.js
и admin/views/*.html, admin/js/main.js, переходный слой LegacyTabView.jsx + legacy-views.js,
дублирующие утилиты async-combobox.js и pagination.js (заменены общими React-компонентами
AsyncCombobox.jsx и Pagination.jsx).
Добавлено 75 React-файлов (~23 200 строк): оболочки четырёх SPA, 15 вкладок админки,
19 сервисов с чистой логикой, общая дизайн-система (react/shared/ui/), render-хелперы для тестов.
Насколько стало лучше
Скорость загрузки и переключения вкладок
| Метрика (gzip) | До (legacy) | После (React) |
|---|---|---|
| Переключение вкладки админки | 2 запроса: fetch HTML-фрагмента + lazy JS |
1 запрос: один lazy-chunk |
| Средний размер вкладки | HTML + JS отдельно | ~5,1 КБ (128 571 байт / 25 chunk'ов) |
| Общие chunk'и (кэшируются между страницами) | — | 79 217 байт (лимит 85 000) |
| Холодная загрузка админки | — | 84 857 байт (лимит 90 000) |
- HTML-фрагменты больше не загружаются через
fetch— вкладка рендерится сразу из одного кэшируемого JS-chunk'а, исчезли двойные сетевые задержки и парсинг HTML на каждое переключение. - Runtime, дизайн-система и утилиты вынесены в общие chunk'и: повторные визиты и переходы между страницами (логин → студент → админка) переиспользуют кэш браузера.
- Каждая вкладка загружается отдельно (
React.lazy+Suspense) — пользователь качает только то, что открывает.
Качество и надёжность
- 237 тестов проходят (
npm run check), против ~170 на момент начала этапа 5: контракты API, payload-валидация, DOM-рендер каждой вкладки, бюджеты bundle, CSP, разрешение всех lazy-вкладок (регрессия на React error #306 поймана и закрыта тестом). - Логика вынесена в чистые сервисы (
*-service.js) — тестируются в Node без браузера и DOM-заглушек. - Единая дизайн-система вместо копипасты виджетов: кастомные селекты,
AsyncCombobox,ConfirmDialog,Pagination,MaskedDateInput— одинаковое поведение и a11y везде. - Устранён класс ошибок ручного DOM: React-state вместо
innerHTML/classList, модалки — условный рендер вместоhidden-флагов, позиционирование меню — Web Animations API.
Безопасность (не ослаблена)
- CSP-хэши:
[]— ни одного элемента вне политики. - JWT по-прежнему только в памяти, без inline-скриптов и inline-стилей
(проверяется тестами
security-policy.test.mjs). - Сообщения об ошибках не вставляют текст исключений через
innerHTML.
Сопровождаемость
- Один стек вместо двух: не нужно поддерживать параллельно vanilla-модули и React.
- −19 000 строк legacy-кода, +4 965 строк тестов.
- URL/REST-контракты и русский UI сохранены — для пользователей миграция незаметна.
Бюджеты bundle (итог, лимиты не поднимались с волны 1)
| Entry point | Размер gzip | Холодная загрузка | Лимиты |
|---|---|---|---|
| Логин | 2 493 | 81 710 | 10 000 / 85 000 |
| Студент | 3 431 | 82 648 | 20 000 / 90 000 |
| Преподаватель | 10 145 | 89 362 | 20 000 / 90 000 |
| Настройки | 8 466 | 87 683 | 20 000 / 90 000 |
| Админ-панель | 5 640 | 84 857 | 20 000 / 90 000 |
| Lazy-вкладки админки | 128 571 (25 chunk'ов, по одной за раз) | — | 150 000 |
Проверка
cd frontend
npm ci
npm run build
npm run check # 237/237 тестов, бюджеты, CSP