Ленивая загрузка контроллеров в Stimulus позволяет оптимизировать производительность веб-приложения, загружая код контроллера только в момент его фактического использования на странице. Это особенно актуально для крупных приложений, где множество контроллеров не требуется сразу при загрузке страницы.
Stimulus работает на основе HTML-атрибутов
data-controller, связывая элементы DOM с соответствующими
JavaScript-классами. В обычной схеме все контроллеры импортируются и
регистрируются заранее:
import { Application } from "@hotwired/stimulus"
import ExampleController from "./controllers/example_controller"
const application = Application.start()
application.register("example", ExampleController)
Проблема в том, что при большом количестве контроллеров весь код загружается сразу, увеличивая время загрузки страницы. Ленивая загрузка решает эту проблему, подключая контроллер только при необходимости.
Stimulus поддерживает динамический импорт контроллеров с
использованием стандартной функции import(). Это позволяет
регистрировать контроллер только тогда, когда элемент появляется на
странице:
import { Application } from "@hotwired/stimulus"
const application = Application.start()
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll("[data-controller]").forEach(async element => {
const controllerName = element.getAttribute("data-controller")
const module = await import(`./controllers/${controllerName}_controller.js`)
application.register(controllerName, module.default)
})
})
Ключевые моменты:
import() возвращает промис, поэтому регистрация
контроллера происходит асинхронно.data-controller с добавлением
_controller.js.data-action для ленивой инициализацииМожно комбинировать ленивую загрузку с событием, чтобы контроллер загружался только при взаимодействии с пользователем:
<button data-controller="lazy" data-action="click->lazy#load">Нажми меня</button>
const application = Application.start()
application.register("lazy", class {
async load(event) {
const module = await import("./controllers/real_controller.js")
application.register("real", module.default)
const controller = application.getControllerForElementAndIdentifier(event.target, "real")
controller.initialize()
}
})
В этом примере контроллер real загружается только при
клике на кнопку, что полностью исключает его загрузку при инициализации
страницы.
stimulus-loadingДля крупных проектов можно использовать специализированные пакеты,
такие как stimulus-loading, которые автоматически
регистрируют контроллеры через динамический импорт на основе структуры
файлов. Это упрощает поддержку кода и снижает вероятность ошибок при
ручной регистрации.
import { Application } from "@hotwired/stimulus"
import { definitionsFromContext } from "@hotwired/stimulus-webpack-helpers"
const application = Application.start()
const context = require.context("./controllers", true, /\.js$/)
application.load(definitionsFromContext(context))
Здесь Webpack автоматически создаёт контекст для всех контроллеров, а их регистрация происходит по мере первого использования.
import(). Для элементов, которые требуют немедленной
реакции, этот подход может потребовать дополнительных обработчиков.Для максимальной эффективности стоит комбинировать ленивую загрузку с другими методами оптимизации:
preload для уменьшения задержки.Ленивая загрузка контроллеров является мощным инструментом оптимизации, позволяющим строить масштабируемые Stimulus-приложения с минимальной нагрузкой на начальную загрузку и плавной реакцией интерфейса.