Code splitting

Code splitting — это техника разделения JavaScript-кода на отдельные части, которые загружаются по мере необходимости. В контексте Slim.js она позволяет создавать легковесные приложения, ускорять начальную загрузку и уменьшать общий размер бандла.


Основы динамического импорта

Slim.js поддерживает современный синтаксис динамического импорта, который позволяет загружать модули асинхронно:

import('./components/MyComponent.js')
  .then(module => {
    const MyComponent = module.default;
    MyComponent.render(document.body);
  })
  .catch(err => console.error('Ошибка загрузки компонента', err));

Ключевые моменты:

  • Асинхронная загрузка: код модуля не включается в основной бандл.
  • Lazy loading компонентов: компонент загружается только тогда, когда он реально нужен.
  • Обработка ошибок: всегда использовать catch для перехвата проблем с загрузкой.

Разделение компонентов

В Slim.js каждый компонент можно оформить как отдельный модуль. Например:

// components/HeavyWidget.js
import { Slim } from 'slim-js';

export default class HeavyWidget extends Slim {
  get template() {
    return `<div>Тяжёлый виджет загружен</div>`;
  }
}
Slim.define('heavy-widget', HeavyWidget);

Затем динамически подключить при необходимости:

button.addEventListener('click', async () => {
  const module = await import('./components/HeavyWidget.js');
  const Widget = module.default;
  const widget = new Widget();
  document.body.appendChild(widget);
});

Такой подход позволяет не загружать тяжелые компоненты при старте, экономя ресурсы и ускоряя первый рендер страницы.


Использование с маршрутизацией

Slim.js часто используют с роутерами типа Navigo или встроенными решениями для SPA. Code splitting прекрасно интегрируется с маршрутизацией:

router.on('/dashboard', async () => {
  const module = await import('./pages/Dashboard.js');
  const Dashboard = module.default;
  Dashboard.render(document.getElementById('app'));
});

router.on('/settings', async () => {
  const module = await import('./pages/Settings.js');
  const Settings = module.default;
  Settings.render(document.getElementById('app'));
});

Преимущества:

  • Каждая страница загружается только при переходе на неё.
  • Основной бандл остаётся минимальным.
  • Улучшается время первого отображения контента.

Взаимодействие с сборщиками

Slim.js легко интегрируется с Webpack, Vite или Rollup, которые поддерживают динамический импорт и автоматическое создание чанков:

  • В Webpack import() автоматически создаёт отдельный файл для модуля.
  • В Vite и Rollup аналогично — каждый динамический импорт становится отдельным бандлом.
  • Можно использовать имена чанков для контроля над формированием файлов:
import(/* webpackChunkName: "dashboard" */ './pages/Dashboard.js');

Советы по оптимизации

  1. Минимизировать количество динамических импортов для критичных компонентов, чтобы не создавать слишком много маленьких чанков.
  2. Разделять по страницам или крупным виджетам, а не по каждой функции.
  3. Предзагрузка часто используемых модулей можно через <link rel="preload"> или метод import() с предварительной загрузкой.
  4. Обработка ошибок при загрузке динамических модулей обязательна для стабильной работы SPA.

Примеры реальных паттернов

Lazy-loading виджетов при скролле:

const observer = new IntersectionObserver(async (entries) => {
  for (const entry of entries) {
    if (entry.isIntersecting) {
      const module = await import('./components/LazyWidget.js');
      const Widget = module.default;
      entry.target.appendChild(new Widget());
      observer.unobserve(entry.target);
    }
  }
});

document.querySelectorAll('.lazy-container').forEach(el => observer.observe(el));

Разделение больших утилит:

async function calculateHeavyData() {
  const { processData } = await import('./utils/heavyProcessing.js');
  return processData();
}

Это позволяет оставлять основной код лёгким, а ресурсоёмкие операции — в отдельных чанках, загружаемых по мере необходимости.


Итоговые принципы

  • Динамические импорты — основной инструмент code splitting.
  • Разделение компонентов и страниц уменьшает размер основного бандла.
  • Интеграция с маршрутизаторами и сборщиками позволяет создавать масштабируемые SPA.
  • Оптимизация загрузки критичных и второстепенных модулей повышает производительность.

Slim.js, благодаря лёгкости и модульной архитектуре, прекрасно сочетает современный подход к code splitting с минимальным объёмом кода.