A comprehensive web component compiler that transforms TypeScript and JSX code into standards-compliant web components with complete development toolchain.
npx @tessl/cli install tessl/npm-stencil--core@4.36.0Stencil is a comprehensive web component compiler that transforms TypeScript and JSX code into standards-compliant web components. Built by the Ionic team, it provides a complete development toolchain including a TypeScript-based component authoring experience with decorators, a powerful build system with code splitting and lazy loading, integrated testing utilities, development server with hot reloading, and screenshot testing capabilities.
npm install @stencil/coreMain component development imports:
import { Component, Prop, State, h } from '@stencil/core';For configuration and build setup:
import { Config } from '@stencil/core';For testing:
import { newSpecPage, newE2EPage } from '@stencil/core/testing';For compiler and build tools:
import { createCompiler } from '@stencil/core/compiler';For mock document utilities:
import { MockDocument } from '@stencil/core/mock-doc';For screenshot testing:
import { ScreenshotConnector } from '@stencil/core/screenshot';For Node.js system utilities:
import { NodeSystem } from '@stencil/core/sys/node';For internal client-side APIs:
import { BUILD } from '@stencil/core/internal/client';import { Component, Prop, State, h } from '@stencil/core';
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true,
})
export class MyComponent {
@Prop() firstName: string;
@Prop() lastName: string;
@State() private isVisible: boolean = true;
render() {
return (
<div>
<p>Hello, {this.firstName} {this.lastName}!</p>
{this.isVisible && <button onClick={() => this.toggle()}>Toggle</button>}
</div>
);
}
private toggle() {
this.isVisible = !this.isVisible;
}
}Stencil is built around several key architectural components:
Core decorators and utilities for creating web components with TypeScript and JSX.
// Component decorators
function Component(opts: ComponentOptions): ClassDecorator;
function Prop(opts?: PropOptions): PropertyDecorator;
function State(): PropertyDecorator;
function Watch(propName: string): MethodDecorator;
function Method(opts?: MethodOptions): MethodDecorator;
function Element(): PropertyDecorator;
function Event(opts?: EventOptions): PropertyDecorator;
function Listen(eventName: string, opts?: ListenOptions): MethodDecorator;
function AttachInternals(): PropertyDecorator;
// JSX and rendering utilities
function h(sel: any, data?: VNodeData | null, ...children: any[]): VNode;
declare const Host: FunctionalComponent<HostAttributes>;
declare const Fragment: FunctionalComponent<{}>;
function render(vnode: VNode, container: Element): void;Configuration system for the Stencil compiler including output targets, dev server, and build optimization.
interface Config extends StencilConfig {
outputTargets?: OutputTarget[];
devServer?: StencilDevServerConfig;
testing?: TestingConfig;
globalStyle?: string;
namespace?: string;
buildEs5?: boolean | 'prod';
}
interface ComponentOptions {
tag: string;
styleUrl?: string;
styleUrls?: string[] | ModeStyles;
styles?: string | { [modeName: string]: any };
shadow?: boolean | ShadowRootOptions;
scoped?: boolean;
assetsDirs?: string[];
formAssociated?: boolean;
}Comprehensive testing framework with unit testing, E2E testing, and screenshot testing capabilities.
// Spec testing
function newSpecPage(opts: NewSpecPageOptions): Promise<SpecPage>;
// E2E testing
function newE2EPage(opts?: NewE2EPageOptions): Promise<E2EPage>;
// Mock utilities
function mockBuildCtx(): BuildCtx;
function mockCompilerCtx(): CompilerCtx;
function mockConfig(): Config;
function mockDocument(): Document;
function mockWindow(): Window;
interface SpecPage {
body: HTMLElement;
doc: Document;
root?: HTMLElement;
rootInstance?: any;
setContent(html: string): Promise<void>;
waitForChanges(): Promise<void>;
}Runtime functions for asset management, mode handling, task scheduling, and component utilities.
// Asset management
function getAssetPath(path: string): string;
function setAssetPath(path: string): string;
// Mode and environment
function getMode<T = string | undefined>(ref: any): T;
function setMode(handler: ResolutionHandler): void;
declare const Build: UserBuildConditionals;
declare const Env: { [prop: string]: string | undefined };
// Task scheduling
function writeTask(task: RafCallback): void;
function readTask(task: RafCallback): void;
// Component utilities
function getElement(ref: any): HTMLStencilElement;
function forceUpdate(ref: any): void;
function getRenderingRef(): any;
// Platform configuration
function setNonce(nonce: string): void;
function setErrorHandler(handler: ErrorHandler): void;
function setPlatformHelpers(helpers: PlatformHelpers): void;Advanced compiler APIs for build tools, plugins, and custom integrations.
interface Compiler {
build(): Promise<CompilerBuildResults>;
createWatcher(): Promise<CompilerWatcher>;
destroy(): Promise<void>;
sys: CompilerSystem;
}
interface CompilerSystem {
name: 'node' | 'in-memory';
version: string;
readFile(p: string): Promise<string>;
writeFile(p: string, content: string): Promise<CompilerSystemWriteFileResults>;
access(p: string): Promise<boolean>;
createDir(p: string): Promise<CompilerSystemCreateDirectoryResults>;
}
interface CompilerBuildResults {
buildId: number;
diagnostics: Diagnostic[];
duration: number;
hasError: boolean;
hasSuccessfulBuild: boolean;
outputs: BuildOutput[];
}Development server configuration and APIs for hot module replacement and live reloading.
interface StencilDevServerConfig {
address?: string;
port?: number;
basePath?: string;
https?: Credentials;
openBrowser?: boolean;
reloadStrategy?: PageReloadStrategy;
experimentalDevModules?: boolean;
logRequests?: boolean;
worker?: boolean;
}
interface DevServer extends BuildEmitEvents {
address: string;
port: number;
browserUrl: string;
close(): Promise<void>;
}// Core component interfaces
interface ComponentInterface {
connectedCallback?(): void;
disconnectedCallback?(): void;
componentWillLoad?(): Promise<void> | void;
componentDidLoad?(): void;
componentWillUpdate?(): Promise<void> | void;
componentDidUpdate?(): void;
componentWillRender?(): Promise<void> | void;
componentDidRender?(): void;
componentShouldUpdate?(newVal: any, oldVal: any, propName: string): boolean | void;
render?(): any;
}
// Virtual DOM types
interface VNode {
$flags$: number;
$tag$: string | number | Function;
$elm$: any;
$text$: string;
$children$: VNode[];
$attrs$?: any;
$name$?: string;
$key$?: string | number;
}
interface VNodeData {
class?: { [className: string]: boolean };
style?: any;
[attrName: string]: any;
}
// Event system
interface EventEmitter<T = any> {
emit: (data?: T) => CustomEvent<T>;
}
interface EventOptions {
eventName?: string;
bubbles?: boolean;
cancelable?: boolean;
composed?: boolean;
}
// Build conditionals
interface UserBuildConditionals {
isDev: boolean;
isBrowser: boolean;
isServer: boolean;
isTesting: boolean;
}
// Functional components
interface FunctionalComponent<T = {}> {
(props: T, children: VNode[], utils: FunctionalUtilities): VNode | VNode[];
}
interface FunctionalUtilities {
forEach: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => void) => void;
map: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => ChildNode) => VNode[];
}
// Task queue
interface RafCallback {
(timeStamp: number): void;
}
interface QueueApi {
tick: (cb: RafCallback) => void;
read: (cb: RafCallback) => void;
write: (cb: RafCallback) => void;
clear?: () => void;
flush?: (cb?: () => void) => void;
}
// HTML element interface
interface HTMLStencilElement extends HTMLElement {
componentOnReady(): Promise<HTMLStencilElement>;
}
// Error handling
type ErrorHandler = (err: any, element?: HTMLElement) => void;
type ResolutionHandler = (elm: HTMLElement) => string | undefined | null;
// Diagnostics
interface Diagnostic {
level: 'error' | 'warn' | 'info' | 'log' | 'debug';
type: string;
messageText: string;
absFilePath?: string;
relFilePath?: string;
lineNumber?: number;
columnNumber?: number;
lines: PrintLine[];
header?: string;
language?: string;
code?: string;
debugText?: string;
}
interface PrintLine {
lineIndex: number;
lineNumber: number;
text?: string;
html?: string;
errorCharStart: number;
errorLength?: number;
}