Vite и Lit

Сочетание Vite и Lit формирует легковесный, высокопроизводительный стек для разработки веб-компонентов. Vite обеспечивает мгновенный dev-сервер с ESM-модулем и оптимизированную сборку, а Lit предоставляет минималистичный слой для создания Web Components с декларативным шаблонизатором и реактивной моделью состояния.

Основная идея интеграции заключается в том, что Lit-компоненты остаются нативными Web Components, а Vite выступает как современная среда разработки, обеспечивающая быстрый HMR, оптимизацию зависимостей и продакшн-бандлинг через Rollup.


Базовая настройка проекта

Стартовая конфигурация Vite для Lit обычно строится на стандартном шаблоне vanilla, с добавлением TypeScript при необходимости.

Создание проекта

npm create vite@latest vite-lit-app
cd vite-lit-app
npm install

Далее установка Lit:

npm install lit

Структура проекта

Типичная структура при использовании Lit:

src/
  components/
    my-element.ts
  styles/
    global.css
  main.ts
index.html
vite.config.ts

Ключевая особенность — отсутствие фреймворк-специфичной обвязки. Lit-компоненты являются самостоятельными модулями.


Создание первого Lit-компонента

Lit использует декораторы и базовый класс LitElement. Компонент описывается как класс с реактивными свойствами и шаблоном.

Пример компонента

import { LitElement, html, css } from 'lit';
import { customElement, property } from 'lit/decorators.js';

@customElement('my-element')
export class MyElement extends LitElement {
  static styles = css`
    p {
      color: blue;
      font-size: 16px;
    }
  `;

  @property({ type: String })
  name = 'Lit';

  render() {
    return html`
      <p>Привет, ${this.name}</p>
    `;
  }
}

Подключение в приложении

import './components/my-element';

document.body.innerHTML = `
  <my-element name="Vite + Lit"></my-element>
`;

Роль Vite в разработке Lit-компонентов

Vite решает несколько ключевых задач при работе с Lit:

  • мгновенная перезагрузка модулей (HMR)
  • нативная работа с ES-модулями
  • оптимизация зависимостей Lit
  • быстрый dev-сервер без бандлинга
  • продакшн-сборка через Rollup

Особенно важно, что Lit-компоненты не требуют дополнительной трансформации — Vite работает напрямую с TypeScript и современным JavaScript.


Конфигурация Vite для Lit

Базовая конфигурация минимальна:

import { defineConfig } from 'vite';

export default defineConfig({
  server: {
    open: true
  },
  build: {
    target: 'es2019'
  }
});

Lit не требует специфического плагина Vite, так как не использует JSX или нестандартные runtime-преобразования.


TypeScript и Lit в Vite

Lit активно используется вместе с TypeScript для типизации свойств и событий компонентов.

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "experimentalDecorators": true,
    "useDefineForClassFields": true
  }
}

Ключевой параметр — experimentalDecorators, необходимый для поддержки декораторов Lit.


Реактивность и обновление состояния

Lit реализует реактивность через декоратор @property. Изменение значения автоматически вызывает повторный рендер.

@property({ type: Number })
count = 0;

increment() {
  this.count++;
}
render() {
  return html`
    <button @click=${this.increment}>
      Счётчик: ${this.count}
    </button>
  `;
}

Vite в этом процессе не участвует напрямую, но обеспечивает мгновенное обновление модуля при изменении кода.


Стилизация компонентов

Lit поддерживает инкапсулированные стили через Shadow DOM. Это хорошо сочетается с Vite, так как стили обрабатываются как JS-строки без дополнительной сборки.

static styles = css`
  :host {
    display: block;
    padding: 12px;
  }

  button {
    background: black;
    color: white;
  }
`;

Дополнительно можно использовать глобальные стили через импорт CSS в Vite:

import './styles/global.css';

Работа с ассетами в Vite + Lit

Vite позволяет импортировать изображения, шрифты и другие ресурсы напрямую в компоненты.

import logo from '../assets/logo.png';

render() {
  return html`<img src=${logo} />`;
}

При сборке Vite оптимизирует и хеширует файлы автоматически.


Динамическая загрузка компонентов

ESM-модель Vite позволяет лениво загружать Lit-компоненты.

await import('./components/heavy-element.js');

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


Работа с событиями

Lit использует стандартные DOM-события, а Vite не вмешивается в их обработку.

dispatchEvent(new CustomEvent('user-select', {
  detail: { id: 1 },
  bubbles: true,
  composed: true
}));

Прослушивание:

document.querySelector('my-element')
  ?.addEventListener('user-select', (e: Event) => {
    console.log((e as CustomEvent).detail);
  });

Оптимизация сборки

Vite использует Rollup в production-режиме, что позволяет эффективно обрабатывать Lit-приложения:

  • tree-shaking неиспользуемых модулей
  • разделение чанков
  • минификация
  • удаление dev-кода

Lit хорошо поддаётся tree-shaking благодаря ESM-структуре импорта:

import { html } from 'lit';

Поддержка HMR

Hot Module Replacement в Vite работает на уровне модулей. Для Lit это означает:

  • обновление шаблонов без перезагрузки страницы
  • сохранение состояния компонента
  • пересборка только изменённого модуля

При изменении render-функции Vite пересылает обновлённый модуль, а Lit повторно применяет шаблон.


Интеграция с роутингом

Хотя Lit не включает встроенный роутинг, Vite легко комбинируется с легковесными решениями.

Пример динамической отрисовки:

const route = location.pathname;

if (route === '/about') {
  await import('./pages/about-page');
}

Такой подход сохраняет минимальный размер бандла.


Подключение сторонних библиотек

Vite оптимизирует зависимости через pre-bundling. Lit совместим с большинством UI- и утилитарных библиотек:

import { debounce } from 'lodash-es';

Важно использовать ESM-версии пакетов для корректного tree-shaking.


Работа с окружением

Vite предоставляет доступ к переменным окружения:

console.log(import.meta.env.VITE_API_URL);

Lit-компоненты могут использовать эти значения напрямую в логике или шаблонах.


SSR и Lit с Vite

Хотя Lit ориентирован на клиентский рендеринг, Vite может использоваться в SSR-сценариях через Node-окружение.

Основной подход:

  • предварительный рендер HTML
  • гидратация на клиенте
  • использование одинаковых компонентов

Lit поддерживает серверный рендеринг через render() в Node-окружении, что позволяет интегрировать его в Vite SSR-пайплайны.


Масштабирование архитектуры

При росте проекта структура с Vite и Lit обычно переходит к модульной модели:

  • компоненты как независимые ESM-модули
  • разделение на feature-модули
  • изоляция стилей в каждом компоненте
  • ленивые страницы через dynamic import

Vite поддерживает такую архитектуру без дополнительного слоя конфигурации, сохраняя скорость разработки и сборки.


Производительность и особенности взаимодействия

Сочетание Vite и Lit обеспечивает:

  • минимальный runtime overhead
  • отсутствие виртуального DOM
  • быстрый cold start dev-сервера
  • предсказуемую сборку

Lit работает напрямую с DOM, а Vite — с модулями, что исключает избыточные абстракции и повышает общую производительность приложения.