Vendor splitting

Vendor splitting — это техника оптимизации загрузки веб-приложений, которая позволяет разделять сторонние зависимости (библиотеки, фреймворки) от основного кода приложения. В Stencil она особенно важна для больших проектов, где использование сторонних библиотек может значительно увеличить размер итогового бандла. Основная цель — ускорить загрузку приложения и улучшить кэширование.


Основы работы

Stencil использует Rollup для сборки проектов. Rollup поддерживает code splitting, что позволяет создавать отдельные чанки для различных частей кода. Vendor splitting реализуется через выделение внешних зависимостей в отдельный бандл.

Пример принципа:

  • app.js — основной код приложения, содержит компоненты, логику, роутинг.
  • vendor.js — сторонние библиотеки, например, lodash, moment, @stencil/core.

При загрузке страницы браузер сначала загружает vendor.js, который может кэшироваться на длительный срок. Изменения в коде приложения не требуют повторной загрузки больших библиотек.


Настройка в Stencil

Stencil поддерживает опцию vendor в конфигурации сборки:

import { Config } from '@stencil/core';

export const config: Config = {
  namespace: 'my-app',
  outputTargets: [
    {
      type: 'www',
      serviceWorker: null,
    },
  ],
  bundles: [
    { components: ['my-component'] }
  ],
  rollupPlugins: {
    after: [],
  },
};

Для явного разделения vendor-кода часто используется конфигурация Rollup через Stencil:

import nodeResolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

export const config: Config = {
  namespace: 'my-app',
  rollupPlugins: {
    before: [
      nodeResolve(),
      commonjs()
    ]
  },
  buildEs5: false,
};

Важный момент: все внешние зависимости нужно помечать как external, чтобы Rollup не включал их в основной бандл приложения:

export const config: Config = {
  namespace: 'my-app',
  rollupConfig: {
    external: ['lodash', 'moment'],
  },
};

Плюсы vendor splitting

  1. Снижение размера основного бандла — пользователи загружают меньше данных при каждом обновлении приложения.
  2. Эффективное кэширование — vendor.js редко меняется, поэтому браузер использует кэш.
  3. Ускорение Time-to-Interactive (TTI) — ускоряется первая интерактивность приложения, так как браузеру нужно обработать меньше кода.

Практические рекомендации

  • Использовать динамический импорт для больших библиотек:

    const { default: _ } = await import('lodash');

    Это позволяет загружать библиотеку только при необходимости.

  • Минимизировать дублирование: если несколько компонентов используют одну и ту же библиотеку, она должна попадать в общий vendor-бандл.

  • Анализировать бандлы: инструменты вроде rollup-plugin-visualizer помогают увидеть, какие библиотеки занимают больше всего места и как их можно вынести в vendor.

  • Совмещать с Lazy Loading компонентов: vendor splitting дает максимальную выгоду, когда часть приложения загружается только при взаимодействии пользователя.


Тонкости в Stencil

  • Stencil автоматически оптимизирует бандлы компонентов, но явное разделение сторонних зависимостей дает более предсказуемый результат.
  • Для веб-компонентов важно, чтобы vendor-код был доступен до рендеринга компонентов, иначе могут возникнуть ошибки из-за отсутствующих зависимостей.
  • При использовании серверного рендеринга (SSR) vendor splitting помогает уменьшить нагрузку на сервер и ускорить отдачу HTML.

Пример структуры итогового проекта

dist/
├─ build/
│  ├─ my-app.entry.js
│  ├─ my-component.js
│  └─ vendor.js
└─ index.html
  • vendor.js содержит все внешние библиотеки.
  • my-app.entry.js — основной бандл приложения.
  • my-component.js — лениво загружаемые компоненты.

Vendor splitting в Stencil — ключевой инструмент для производительных веб-приложений, позволяющий разделять сторонние зависимости и основной код, ускорять загрузку страниц и оптимизировать кэширование. При правильной конфигурации и использовании динамических импортов достигается значительное улучшение производительности даже в крупных проектах.