Типичные проблемы и решения

Неправильная инициализация проекта

Одна из самых распространённых проблем — некорректная настройка проекта. Stencil требует строгого соответствия структуре каталогов и конфигурации stencil.config.ts. Часто ошибки появляются при:

  • Некорректном указании пути к src/components
  • Отсутствии обязательных зависимостей (@stencil/core, typescript)
  • Использовании устаревшей версии Node.js

Решения:

  • Проверять версию Node.js и npm/yarn перед созданием проекта. Рекомендуется Node.js версии 18+.
  • Использовать команду npm init stencil для автоматической генерации структуры.
  • Проверять файл tsconfig.json на корректность путей и целевых версий.

Ошибки при сборке и компиляции

Stencil использует TypeScript и Rollup, поэтому частыми являются ошибки сборки:

  • Cannot find module при импортах компонентов
  • Проблемы с декораторами (@Prop(), @State(), @Event())
  • Конфликты типов в TypeScript

Решения:

  • Проверять правильность импортов, особенно при использовании абсолютных и относительных путей.
  • Использовать npm run build -- --debug для вывода подробного лога.
  • Проверять совместимость типов, особенно при работе с объектами и массивами в @Prop() и @State().

Некорректное обновление состояний компонентов

Stencil активно использует реактивность через @State и @Prop. Частые проблемы:

  • Изменения в состоянии не вызывают перерендер компонента
  • Массивы и объекты не отслеживаются корректно при прямой мутации

Решения:

  • Использовать методы обновления состояния через новый объект или массив:
this.items = [...this.items, newItem];
  • Не изменять объекты или массивы напрямую (this.obj.prop = value), вместо этого создавать новый объект:
this.obj = { ...this.obj, prop: value };

Проблемы с событиями и декоратором @Event

Ошибки с пользовательскими событиями:

  • Событие не ловится внешним компонентом
  • Событие генерируется, но detail всегда пустой

Решения:

  • Всегда указывать { bubbles: true, composed: true } при создании события:
@Event({ bubbles: true, composed: true }) myEvent: EventEmitter<string>;
  • Использовать this.myEvent.emit(data) для передачи данных.
  • Проверять, что слушатель привязан к правильному элементу и подключён после рендеринга компонента.

Стилизация и Shadow DOM

Stencil по умолчанию использует Shadow DOM, что иногда вызывает проблемы со стилями:

  • Стили не применяются к вложенным элементам
  • Внешние CSS-файлы игнорируются

Решения:

  • Использовать :host для стилизации корневого элемента компонента:
:host {
  display: block;
  color: red;
}
  • При необходимости глобальных стилей использовать @import в global.css или :host-context() для контекста:
:host-context(.theme-dark) {
  background: black;
}
  • Для доступа к внутренним элементам Shadow DOM использовать ::part и ::slotted.

Проблемы с маршрутизацией и Lazy Loading

Stencil поддерживает ленивую загрузку компонентов и встроенный роутер. Частые проблемы:

  • Компонент не загружается при переходе на страницу
  • Ошибки вида custom element not defined

Решения:

  • Использовать динамический импорт для ленивых компонентов:
const lazyComponent = await import('./my-component');
  • Убедиться, что путь к компоненту корректный и экспортирован через export в index.ts.
  • Проверять, что все компоненты зарегистрированы до использования в DOM.

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

Ошибки производительности возникают при:

  • Частых обновлениях состояния больших массивов
  • Сложных вычислениях в методах рендеринга
  • Избыточных слушателях событий

Решения:

  • Использовать мемоизацию вычислений через вспомогательные методы или хранилище состояния вне компонента.
  • Ограничивать количество @State и @Prop, объединяя связанные данные.
  • Применять shouldComponentUpdate для контроля перерендеров:
shouldComponentUpdate(newValue, oldValue) {
  return newValue !== oldValue;
}

Интеграция с другими фреймворками

Stencil легко интегрируется с React, Angular, Vue, но типичные ошибки:

  • Компоненты не рендерятся при использовании в React
  • Пропсы не передаются корректно
  • События не ловятся нативными слушателями

Решения:

  • Для React использовать обёртку react-wrapper или defineCustomElements(window).
  • Следить за регистром названий компонентов: HTML использует kebab-case.
  • Использовать корректные типы событий и обработчиков для разных фреймворков.

Работа с тестированием

Тестирование компонентов Stencil через Jest и E2E часто сталкивается с:

  • Ошибками при рендере Shadow DOM
  • Недоступностью слотов или внутренних элементов

Решения:

  • Использовать newSpecPage для юнит-тестов:
const page = await newSpecPage({
  components: [MyComponent],
  html: `<my-component></my-component>`
});
  • Для E2E тестов применять page.find('selector') с учётом Shadow DOM.
  • Использовать slot и shadowRoot правильно, чтобы элементы были доступны для тестов.

Эти подходы и практики позволяют минимизировать распространённые ошибки при разработке с использованием Stencil и обеспечивают стабильность компонентов при масштабировании проекта.