Stencil — это компилятор для создания веб-компонентов, который сочетает в себе преимущества современного JavaScript и веб-стандартов. Основная цель Stencil — генерировать высокопроизводительные, переиспользуемые компоненты, которые работают в любом современном браузере без зависимости от фреймворков. Расширение функционала начинается с понимания базовой архитектуры и жизненного цикла компонентов.
Каждый компонент Stencil определяется с помощью декоратора
@Component, который задает имя компонента, путь к шаблону и
стилям:
import { Component, Prop, State, h } from '@stencil/core';
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
@Prop() title: string;
@State() count: number = 0;
render() {
return (
<div>
<h1>{this.title}</h1>
<p>{this.count}</p>
</div>
);
}
}
Ключевые моменты:
@Prop() — свойства компонента, которые могут
передаваться извне.@State() — внутренние реактивные состояния.shadow: true — использование Shadow DOM для изоляции
стилей.Stencil предоставляет набор хуков, позволяющих расширять поведение компонентов:
componentWillLoad() — вызывается до первого
рендера.componentDidLoad() — после первого рендера и вставки в
DOM.componentWillUpdate() и
componentDidUpdate() — перед и после обновления
компонента.componentDidUnload() — перед удалением компонента из
DOM.Использование этих методов позволяет внедрять стороннюю логику, производить асинхронные операции и управлять состояниями.
componentWillLoad() {
console.log('Компонент загружается');
}
componentDidLoad() {
this.fetchData();
}
Stencil поддерживает кастомные события с помощью декоратора
@Event и эмиссии событий через
EventEmitter:
import { Event, EventEmitter } from '@stencil/core';
@Event() itemSelected: EventEmitter<string>;
selectItem(item: string) {
this.itemSelected.emit(item);
}
События можно слушать на уровне родительских компонентов или через стандартный DOM:
<my-component onItemSelec ted="handleSelection"></my-component>
Слоты (<slot>) позволяют внедрять произвольный
контент внутрь компонентов:
render() {
return (
<div>
<slot name="header"></slot>
<slot></slot>
</div>
);
}
Слоты можно комбинировать с состояниями и событиями для создания гибких и переиспользуемых компонентов.
Stencil позволяет создавать декораторы свойств и методов для расширения функционала:
@Watch(propName) — отслеживание изменений
свойства.@Method() — публичные методы компонента, доступные
через DOM.@Watch('title')
watchTitle(newValue: string, oldValue: string) {
console.log('Title изменился с', oldValue, 'на', newValue);
}
@Method()
async resetCount() {
this.count = 0;
}
Stencil интегрируется с внешними библиотеками и утилитами. Возможна генерация динамических компонентов на основе JSON-схем, подключение RxJS для реактивного потока данных, а также использование CSS-in-JS для динамических стилей.
import { Observable } from 'rxjs';
data$: Observable<number>;
componentWillLoad() {
this.data$.subscribe(value => {
this.count = value;
});
}
Stencil поддерживает плагины, которые могут изменять процесс компиляции. Можно писать генераторы компонентов, внедрять кастомные трансформации JSX и создавать middleware для обработки атрибутов и стилей.
// пример плагина, который добавляет префикс ко всем тегам
export function prefixPlugin() {
return {
transformNode(node) {
node.tagName = `prefix-${node.tagName}`;
return node;
}
}
}
Stencil поддерживает ленивую загрузку компонентов
(lazy loading), что критично для производительности больших
приложений. Компоненты автоматически разделяются на чанки, и браузер
подгружает их только при необходимости. Этот механизм можно расширять с
помощью кастомных условий подгрузки, например, Intersection
Observer.
@Component({
tag: 'lazy-component',
shadow: true,
assetsDirs: ['assets']
})
export class LazyComponent {}
С помощью Stencil можно создавать веб-компоненты для React, Angular, Vue. Расширение функционала в этих случаях включает генерацию адаптеров и типов, что позволяет безболезненно интегрировать Stencil-компоненты в существующие проекты.
import { defineCustomElements } from 'my-component-library/loader';
defineCustomElements(window);
Расширение возможностей Stencil часто связано с настройкой
stencil.config.ts:
export const config: Config = {
namespace: 'my-lib',
outputTargets: [
{ type: 'dist' },
{ type: 'www', serviceWorker: null }
]
};
Расширение функционала Stencil требует глубокого понимания архитектуры компонентов, жизненного цикла, событий и возможностей интеграции. Комбинация декораторов, хуков, слотов и плагинов позволяет создавать мощные и гибкие веб-компоненты, готовые к использованию в любых современных проектах.