1.3 Управление зависимостями плагинов
SFLoaderPlugin поддерживает зависимости между модулями через поле relation в правилах SF.RuleLoader.
Зависимость означает: если найден основной модуль, loader должен добавить связанные модули в очередь загрузки и дождаться
их готовности перед запуском JS основного модуля.
Это используется не только для внешних библиотек вроде jquery, но и для связи Smart-компонентов с обычными
component-модулями. Например, Smart-компонент cl-tooltip зависит от component-модуля tooltip.
Формат relation
Зависимости описываются прямо в правиле модуля:
SF.RuleLoader['dropdown'] = {
regex: /sf-dropdown|sf-list-item/,
type: 'component',
js: true,
css: true,
relation: [{ name: 'icon-buttons' }],
};
Поле relation — это массив объектов. Минимальный объект содержит имя зависимости:
relation: [{ name: 'icon-buttons' }]
При необходимости можно указать режим или ресурсы явно:
SF.RuleLoader['fancybox'] = {
regex: /data-fancybox/,
type: 'attribute',
mode: 'component',
js: true,
css: true,
relation: [{ name: 'jquery', mode: 'component', js: true }],
};
Частые поля relation-объекта:
name— имя зависимого модуля;mode— категория загрузки зависимости, если её нужно указать явно;js,css— подсказки по ресурсам, когда зависимость описана не полностью или подключается особым способом.
Старый формат вида { relations: { "fancybox": ["jquery"] } } не является основным контрактом текущего frontend-loader.
Сейчас зависимости должны жить рядом с правилом модуля в SF.RuleLoader.
Как loader собирает зависимости
Когда discovery находит модуль, loader вызывает внутреннюю логику добавления модуля в список загрузки. Если у правила есть
relation, выполняется setRelation():
- Зависимости добавляются в
relationPluginsдля основного модуля. - Имена зависимостей добавляются в общий список модулей.
- Для каждой зависимости определяется категория загрузки.
- Если у зависимости есть собственные
relation, они обрабатываются рекурсивно.
Категория зависимости определяется так:
- если в relation-объекте указан
mode, используется он; - если правило зависимости имеет
type: 'smart', используетсяsmart; - если правило имеет
type: 'component'илиtype: 'attribute', используетсяcomponent; - иначе зависимость считается
utility.
Для рекурсивного обхода используется защита от повторного прохода по одному и тому же имени, чтобы не зациклиться на ошибочных или перекрёстных зависимостях.
Порядок загрузки
В standAlone-режиме loader строит пути и подключает файлы на клиенте. Для модулей с зависимостями он использует
следующую схему:
- Основной модуль найден и добавлен в очередь.
- Loader видит
relationи начинает загрузку зависимостей. - Для каждой зависимости проверяется, не загружена ли она уже.
- Loader ждёт готовность JS/CSS зависимости по её правилу.
- Когда все зависимости готовы, подключается JS основного модуля.
Важно: CSS основного component-модуля может подключаться отдельно от его JS. Зависимости удерживают именно запуск JS основного модуля, чтобы код не стартовал раньше нужных ресурсов.
Серверный режим
Если standAlone выключен, frontend-loader отправляет информацию о зависимостях на сервер в параметре relations:
/simai/loader/loader.php?a=dropdown&relations={"dropdown":["icon-buttons"]}
Этот параметр — внутренний транспорт между frontend-loader и серверным loader. Его не нужно воспринимать как основной
способ описания зависимостей в клиентском коде. Исходный контракт всё равно остаётся в SF.RuleLoader[*].relation.
Сервер использует список модулей и relations, чтобы подготовить корректный набор JS/CSS и кэш.
Примеры
Component зависит от component
SF.RuleLoader['dropdown'] = {
regex: /sf-dropdown|sf-list-item/,
type: 'component',
js: true,
css: true,
relation: [{ name: 'icon-buttons' }],
};
Если на странице найден dropdown, loader также загрузит icon-buttons.
Smart-компонент зависит от component
SF.RuleLoader['cl-tooltip'] = {
tags: ['sf-tooltip'],
type: 'smart',
mode: 'smart',
js: true,
relation: [{ name: 'tooltip' }],
};
Если в DOM найден <sf-tooltip>, loader загрузит Smart-модуль cl-tooltip и связанный component-модуль tooltip.
Несколько зависимостей
SF.RuleLoader['cl-icon-buttons'] = {
tags: ['sf-icon-button'],
type: 'smart',
mode: 'smart',
js: true,
relation: [{ name: 'icon-buttons' }, { name: 'cl-icons' }],
};
Основной модуль будет готов к запуску только после обработки обеих зависимостей.
Повторная загрузка
Loader хранит состояние загрузки модулей:
- уже загруженная зависимость не подключается повторно;
- зависимость, которая уже находится в процессе загрузки, не запускается второй раз;
- основной модуль ждёт завершения текущей загрузки зависимости;
- отсутствующие файлы фиксируются в
SF_MISSING_PLUGINS.
Особенности
relationрасширяет список загрузки, но сам по себе не является каналом discovery.- Зависимость может принадлежать другому смысловому набору:
component,smartилиutility. - Если
modeне указан, loader пытается вывести его по правилу зависимости. - Многоуровневые зависимости поддерживаются рекурсивно.
- Ошибочная или отсутствующая зависимость приведёт к предупреждению в консоли и может нарушить работу основного модуля.