
Fast, Reactive Web Components
André Gonçalves
Web Components
- Natively-supported, standardized JavaScript components
- Reusable and encapsulated away from the rest of your code
- Run in every framework or on their own
- Answer to the shared-component problem
- Native browser support: Chrome, Safari, good polyfills
Web Components
- Custom Elements
- HTML Templates
- Shadow DOM
- HTML imports
Custom Element Example
<my-component size="large" theme="light"/></my-component>
Custom Element Example
class MyComponent extends HTMLElement {
createdCallback() {
// Standard DOM/fetch/etc. code...
}
attachedCallback() {}
detachedCallback() {}
attributeChangedCallback() {}
}
document.registerElement('my-component', MyComponent);
Making it easier to build Custom Elements
- Framework features
- Desire to manage bundles of components
- Automatic Polyfilling when necessary
Stencil: A Compiler for Web Components
What is Stencil?
- A compiler that generates Custom Elements, part of the Web Components spec
- Not a framework: output is 100% standards-compliant Custom Elements
- Adds powerful framework features to Web Components
- Created and used heavily by the Ionic Framework team. Ionic 4+ is built on it!
Why?
- Performance: Traditional frameworks proving too heavy for demanding mobile Progressive Web Applications
- Stability: Desire to use web standards and avoid constant framework churn
- Interoperability: Ability to create components that work across all major frameworks.
- Familiarity: features from frameworks but in a leaner, standards-compliant package
Example Stencil Component
import { Component, Prop } from '@stencil/core';
@Component({
tag: 'my-name',
styleUrl: 'my-name.scss'
})
export class MyName {
@Prop() name: string;
render() {
return (
<p>
Hello, my name is {this.name}
</p>
);
}
}
Stencil-compiled Components have
- Virtual DOM: fast DOM updates without common DOM performance pitfalls
- Lazy Loading: By default components load asyncronously and can be bundled with related components
- Reactivity: Efficient updates based on property and state changes
Stencil-compiled Components have (cont.)
- High-performance Rendering: async rendering system, similar to React Fiber
- JSX: Popular and familiar markup system pioneered by React
- Server Side Rendering: Hydrate pre-compiled components on the server without a headless browser
Stencil API
- @Component(): set tag name and associated stylesheet (Sass or plain CSS)
- @Prop(): Create a property on the component
- @State(): local state that should be watched during change detection
- @Event(): Trigger events on a component
- @Listen(): listen for events fired from children
- @Element(): grab the DOM element for this component
Example Stencil Component
import { State } from '@stencil/core';
...
export class TodoList {
@State() completedTodos: Todo[];
completeTodo(todo: Todo) {
this.completedTodos.push(todo);
}
render() {
return (
<div>
{this.todos.map((todo) =>
<div>
<div>{todo.taskName}</div>
<div>{todo.isCompleted}</div>
</div>
)}
</div>
)
}
}
How is Stencil different from X?
- Angular/React/Vue/etc.: Stencil builds standards-based web components that run natively in the browser.
- Polymer: Stencil works primarily at build rather than runtime. Outputs vanilla web components. Opinionated around JSX, Virtual DOM, and other framework features.
- Vanilla Web Components: Stencil provides complicated framework features as if you wrote them yourself in vanilla Web Components.
Questions?
- Andre
- @andregoncalves
- github.com/andregoncalves