Админка, настройки, логин, кабинеты преподавателя и студента полностью переведены на 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
102 lines
6.4 KiB
Markdown
102 lines
6.4 KiB
Markdown
# Итоги миграции frontend на React
|
||
|
||
Дата завершения: 28.09.2026. Полный журнал процесса — в [`REACT_MIGRATION.md`](REACT_MIGRATION.md),
|
||
архитектура итогового решения — в [`FRONTEND.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 |
|
||
|
||
---
|
||
|
||
## Проверка
|
||
|
||
```bash
|
||
cd frontend
|
||
npm ci
|
||
npm run build
|
||
npm run check # 237/237 тестов, бюджеты, CSP
|
||
```
|