Continuous Integration настройка

Lit — это современный фреймворк для создания веб-компонентов на JavaScript, обеспечивающий высокую производительность и удобство работы с реактивными данными. Ключевым элементом Lit является класс LitElement, от которого наследуются все компоненты. Основная структура компонента выглядит следующим образом:

import { LitElement, html, css } from 'lit';

class MyComponent extends LitElement {
  static styles = css`
    :host {
      display: block;
      padding: 16px;
      background-color: #f0f0f0;
    }
    p {
      color: #333;
    }
  `;

  static properties = {
    title: { type: String },
    count: { type: Number },
  };

  constructor() {
    super();
    this.title = 'Пример компонента';
    this.count = 0;
  }

  render() {
    return html`
      <h1>${this.title}</h1>
      <p>Счетчик: ${this.count}</p>
      <button @click=${() => this.count++}>Увеличить</button>
    `;
  }
}

customElements.define('my-component', MyComponent);

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

  • Стилизация через static styles позволяет изолировать CSS для компонента.
  • Свойства (properties) автоматизируют обновление шаблона при изменении данных.
  • События (@click) связывают DOM с методами класса без прямого использования addEventListener.

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

Lit использует реактивную модель: любое изменение свойства, объявленного в static properties, вызывает повторный рендер компонента. Это позволяет строить динамические интерфейсы без ручного управления DOM. Важно понимать различие между:

  • Примитивами (String, Number, Boolean) — обновления происходят автоматически при присвоении нового значения.
  • Объектами и массивами — для реактивности требуется создавать новые объекты или использовать requestUpdate() для принудительного рендера.

Пример:

this.items = [...this.items, newItem]; // создается новый массив, триггерится обновление
this.requestUpdate(); // принудительное обновление, если объект изменен мутацией

Шаблоны и директивы

Lit использует шаблоны HTML, встроенные в JavaScript с помощью html. Для управления динамикой применяются директивы:

  • repeat — для рендеринга списков:
import { repeat } from 'lit/directives/repeat.js';

render() {
  return html`
    <ul>
      ${repeat(this.items, item => item.id, item => html`<li>${item.name}</li>`)}
    </ul>
  `;
}
  • ifDefined — для условной вставки атрибутов:
import { ifDefined } from 'lit/directives/if-defined.js';
html`<img src=${ifDefined(this.imageUrl)} />`
  • classMap и styleMap — динамическое управление классами и стилями:
import { classMap } from 'lit/directives/class-map.js';

html`<div class=${classMap({ active: this.isActive, disabled: !this.isEnabled })}></div>`

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

Lit поддерживает слоты для создания гибких и переиспользуемых компонентов. Слоты позволяют вставлять произвольный HTML внутрь компонента:

render() {
  return html`
    <section>
      <header><slot name="header"></slot></header>
      <main><slot></slot></main>
      <footer><slot name="footer"></slot></footer>
    </section>
  `;
}

Использование:

<my-component>
  <h1 slot="header">Заголовок</h1>
  <p>Основной контент</p>
  <small slot="footer">Подвал</small>
</my-component>

Интеграция с CI/CD

Для крупных проектов Lit компоненты должны проходить непрерывную интеграцию (Continuous Integration, CI). Основные шаги:

  1. Сборка проекта: используем vite или rollup для генерации продакшн-бандла.
  2. Запуск тестов: библиотека @web/test-runner совместно с @open-wc/testing позволяет писать юнит- и интеграционные тесты для веб-компонентов.
  3. Линтинг и форматирование: ESLint и Prettier проверяют код на соответствие стандартам и стилю.
  4. Сборка документации: Storybook или Lit DevTools помогают документировать компоненты и визуально проверять состояния.

Пример конфигурации GitHub Actions для CI:

name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run lint
      - run: npm run test
      - run: npm run build

Тестирование Lit-компонентов

  • Unit-тесты: проверяют отдельные компоненты и методы.
  • Integration-тесты: тестируют взаимодействие нескольких компонентов.
  • Visual regression: сравнивают визуальное отображение компонентов с эталонным состоянием.

Пример теста с @open-wc/testing:

import { fixture, html, expect } from '@open-wc/testing';
import './my-component.js';

describe('MyComponent', () => {
  it('рендерит заголовок', async () => {
    const el = await fixture(html`<my-component title="Тест"></my-component>`);
    expect(el.shadowRoot.querySelector('h1').textContent).to.equal('Тест');
  });
});

Оптимизация и производительность

Lit применяет shady DOM и shadow DOM для изоляции стилей и минимизации перерисовок. Для повышения производительности:

  • Использовать shouldUpdate(changedProps) для контроля обновлений.
  • Минимизировать мутации больших массивов и объектов.
  • Использовать директивы cache для сохранения шаблонов, которые редко меняются.

Пример:

import { cache } from 'lit/directives/cache.js';

render() {
  return html`${cache(this.isLoaded ? html`<p>Загружено</p>` : html`<p>Загрузка...</p>`)}`;
}

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

Типичная структура:

src/
  components/
    my-component.js
  styles/
    variables.css
  index.js
tests/
  my-component.test.js
public/
  index.html
vite.config.js
package.json
  • components/ — отдельные веб-компоненты.
  • styles/ — глобальные переменные и общие стили.
  • tests/ — юнит- и интеграционные тесты.
  • public/ — статические файлы для сборки.
  • index.js — точка входа приложения.

Эта организация упрощает интеграцию в CI/CD и масштабирование больших проектов.