Ленивая загрузка в SkateJS предназначена для уменьшения времени первого рендера и общего объёма передаваемого кода. Механизм основан на динамическом импорте модулей ES и отложенной регистрацией веб-компонентов, что позволяет избегать загрузки крупных виджетов до момента их фактического появления в DOM или потребности в их функциональности.
SkateJS использует нативные веб-компоненты и интеграцию с модульной
архитектурой JavaScript. Вместо предварительной регистрации всех
кастомных элементов на этапе инициализации приложения, компоненты могут
быть экспортированы как функции, возвращающие промис, который загружает
код по запросу. Регистрация компонента происходит только после
осуществления динамического импорта и вызова
customElements.define.
Поскольку SkateJS не накладывает собственного бандлера, ленивую
загрузку удобно комбинировать с Vite, Webpack или Rollup. Каждый из них
поддерживает разбиение кода на чанки и динамический импорт посредством
синтаксиса import().
Часто в интерфейсе присутствуют крупные компоненты, вроде таблицы с виртуальным скроллом, сложного селекта или области редактирования. Их перенос в отдельный чанк позволяет загрузить лишь при обращении к элементу:
// не регистрируем компонент сразу
let LoadedEditor = null;
async function ensureEditor() {
if (!LoadedEditor) {
LoadedEditor = (await import('./components/editor.js')).default;
customElements.define('app-editor', LoadedEditor);
}
}
Дальнейшее использование происходит при появлении тега
app-editor в DOM: механизм наблюдения за DOM инициирует
вызов ensureEditor и регистрирует компонент перед первым
рендером.
Отложенная загрузка особенно эффективна совместно с
IntersectionObserver. Определяется зона просмотра, в
которой компонент становится видимым. При пересечении порога наблюдения
происходит загрузка чанка и регистрация элемента. Такой подход
минимизирует сетевую активность и исключает загрузку элементов, которые
пользователь не видит.
const observer = new IntersectionObserver(async entries => {
for (const entry of entries) {
if (entry.isIntersecting) {
await ensureEditor();
observer.unobserve(entry.target);
}
}
});
Целевой DOM-узел добавляется в наблюдение сразу после его вставки в документ.
После загрузки компонента возникает задача корректной передачи
состояния и атрибутов, которые могли быть прописаны заранее. SkateJS
использует декларативное связывание свойств и атрибутов, поэтому
реализованный компонент получает текущие значения при первом создании
экземпляра. Если необходима инициализация, связанная с внешними данными,
она переносится в connectedCallback или в функцию
рендеринга с проверкой готовности зависимостей.
Ленивая загрузка может повысить задержку первого рендера компонента. Чтобы минимизировать визуальный разрыв, применяется два приёма:
SkateJS совместим с библиотеками виртуального DOM и шаблонизации, такими как lit-html. Их подключение не мешает применению правок для загрузки по требованию, поскольку импорт может быть отложен вместе с компонентом.
Компонент, загруженный лениво, должен корректно взаимодействовать с глобальными системами: шиной событий, состоянием приложения или роутером. Поскольку код компонента отсутствует до загрузки, события, приходящие до момента регистрации, могут быть потеряны. Поэтому применяются буферизация событий или запрос состояния после подключения.
Браузер кэширует загруженные чанки, благодаря чему повторное
появление компонента в интерфейсе не приводит к дополнительной загрузке.
При миграции между страницами внутри SPA реинициализация сводится к
повторному вызову customElements.define, который будет
проигнорирован, если элемент уже зарегистрирован.
При использовании Webpack применяется
/* webpackChunkName: "editor" */ для удобного именования
чанков и последующего анализа. Rollup и Vite автоматически формируют
чанки на основе дерева зависимостей динамического импорта. Важно следить
за тем, чтобы крупные зависимости не попадали целиком в основной бандл,
иначе выгода от лени появится лишь частично.
Тестирование осуществляется в два этапа:
Используются изолированные окружения и мокирование методов
import(), чтобы не зависеть от реального разделения
кода.
Измерение влияния ленивой загрузки проводится при помощи показателей Time to Interactive, Largest Contentful Paint и объёма основного бандла. На больших интерфейсах SkateJS даёт заметное сокращение времени отображения ключевых элементов за счёт отложенного подключения второстепенных компонентов.