Тема
Оптимизация загрузки и бандла. Изоляция сущностей tenant’ов
Одна потребность: (1) уменьшить размер начальной загрузки и время до интерактивности за счёт code splitting и ленивой загрузки; (2) не допустить, чтобы сущности (конфигурация, код, данные) одной компании (tenant) попадали в бандл или в контекст другой — критично для мультитенантности и безопасности.
Зачем это нужно (мировой опыт)
- Performance: большие монолитные бандлы увеличивают время загрузки и парсинга; code splitting по маршрутам и по фичам — стандарт (Webpack/Vite chunks, dynamic import). Core Web Vitals и UX напрямую зависят от размера начального бандла.
- Multi-tenancy и изоляция: в SaaS и enterprise платформах данные и конфигурация одного tenant не должны быть доступны другому. Утечка в бандл означает, что при загрузке приложения для компании A в JavaScript или в предзагруженных данных может оказаться конфигурация компании B — нарушение конфиденциальности и регуляторики (GDPR и др.).
- Лучшие практики: конфигурация tenant подгружается после идентификации (после логина или по домену); код, специфичный для фичи/модуля, загружается лениво; общий код — в shared chunks без привязки к tenant.
Текущее состояние
- Маршруты: компоненты страниц загружаются лениво (
() => import('@/features/...')), что даёт разбиение по маршрутам. Админка, расписание, рейсы, логин и т.д. — отдельные чанки. - Vite: один entry, chunks формируются по динамическим импортам; нет явного разделения «базовый бандл» и «tenant-specific» или «feature-specific» чанки по политике.
- Данные и конфигурация: домен (проекты, типы, запросы и т.д.) загружается с бэкенда после инициализации; если в ответ API попадают данные только текущего tenant и бэкенд не отдаёт чужие — утечки через сеть нет. Риск — если конфигурация или данные какого-то tenant попадут в статику (например, в build-time подстановку) или в один общий чанк с данными нескольких tenant’ов.
- Сборка: нет разделения сборки «по tenant’ам» (отдельный бандл под каждую компанию); приложение одно, tenant определяется в рантайме (логин, домен, заголовок). Поэтому изоляция должна обеспечиваться тем, что в бандл не попадают подставляемые на сборке данные другого tenant’а, а все tenant-specific данные приходят только через API после определения контекста.
Что сделать
1. Запретить подстановку tenant-данных в бандл на сборке
- Никакие идентификаторы tenant’ов, конфигурация конкретной компании, персональные или конфиденциальные данные не должны подставляться в код на этапе сборки (например, через env или генерируемый конфиг) так, чтобы они попали в общий бандл. Если используется сборка «под tenant» (редкий кейс), артефакты сборки должны быть строго разделены по tenant’ам и не смешиваться при раздаче.
- Конфигурация и данные tenant — только из API (или из runtime env после аутентификации). Проверка при code review и при аудите: в репозитории и в артефактах сборки нет хардкода tenant-id и чужих данных.
2. Code splitting и ленивая загрузка
- Критичный путь: только то, что нужно для первого экрана и для проверки auth/health. Остальное — динамический import по маршруту или по фиче (админка, тяжёлые отчёты, графические и специфичные модули). Уже используется для страниц; расширить на тяжёлые виджеты и библиотеки (например, Monaco и тяжёлые графики), если они не на первом экране.
- Именованные чанки (Vite:
manualChunksили комментарии/* webpackChunkName: "admin" */) для предсказуемого разбиения: base, vendor (Vue, router, общие библиотеки), admin, preview и т.д. Так сущности одной фичи/приложения не «перетекают» в чанк другой без необходимости. - Избегать импорта всего tenant-специфичного конфига в корне приложения; подгружать конфиг/словари после определения tenant (после логина или после чтения контекста из API).
3. Разделение по фичам и приложениям
- Модули фич (features) импортировать лениво там, где они нужны. Не делать в корне один импорт «все фичи», иначе бандлер соберёт их в один чанк или в главный бандл. Так «сущности одной компании» в смысле фичи (например, модуль заказчика A) не попадут в бандл заказчика B, если у B эта фича не подключена — при условии, что подключение фич тоже идёт через динамический импорт по конфигурации.
- Если в одном инстансе приложения несколько независимых фич: каждая со своими маршрутами и чанками; общий код — в shared. Проверить, что при входе в одну фичу не подгружаются тяжёлые чанки другой, пока пользователь туда не перешёл.
4. Аудит и процесс
- В регламент сборки и деплоя включить проверку: в артефактах нет tenant-id и конфиденциальных данных; при необходимости — автоматический скрипт поиска паттернов (tenant id, имена компаний) в сгенерированных чанках.
- Документировать для разработчиков: не класть в статику и в env на сборке данные, зависящие от tenant; tenant-specific — только через API после определения контекста.
Риски и ограничения
- Избыточный code splitting увеличивает число запросов при навигации; баланс между размером начального бандла и количеством чанков. Аудит на утечку tenant-данных в артефакты нужно включить в CI; при сборке «под tenant» артефакты должны храниться и раздаваться строго раздельно.
Вывод
- Изоляция tenant’ов: никаких подстановок tenant-данных в бандл на сборке; конфигурация и данные tenant — только из API в рантайме. Аудит артефактов и процесса.
- Оптимизация бандла: критичный путь минимален; остальное — code splitting по маршрутам и фичам, ленивая загрузка тяжёлых модулей, именованные чанки для предсказуемого разбиения.
- Сущности одной компании (фичи, модули) не перетекают в чанк другой за счёт ленивых импортов и отсутствия общих статических данных tenant’ов в бандле.