Stencil: a New Hope of Web Components

Stencil: a New Hope of Web Components

It is hard to migrate from existing framework/library to new technology, especially when you already developed the huge library used across teams and projects. Migrating from framework A to framework B usually means complete re-writing all existing components and business logic. But could we avoid such situations in the future? The answer is in Web Components spec and Stencil is a compiler with superpowers.


Vitalii Bobrov

December 13, 2017


  1. 3.

    Outline • Motivation • Introduction to Web Components • Introduction

    to Stencil • Stencil API • How to get started
  2. 20.

    Browsers Support Chrome Safari Firefox Edge IE 11 JS Modules

    ☹ Custom Elements ☹ ☹ Templates ☹ Shadow DOM ☹ ☹
  3. 23.

    Reasons to Use • Natively-supported, standardized JavaScript components • Run

    in every framework or on their own • Answer to the shared-component problem • Powered by the Custom Element spec • Native browser support: Chrome, Safari, good polyfills
  4. 26.

    class LightSaber extends HTMLElement { static get observedAttributes() { return

    ['size', 'color', 'active']; } attributeChangedCallback(name, oldValue, newValue) { switch(name) { case 'size': // React on change. break; case 'color': // React on change. break; case 'active': // React on change. break; default: break; } } } window.customElements.define('light-saber', LightSaber); Element Declaration
  5. 27.

    constructor() { super(); const shadowRoot = this.attachShadow({mode: 'open'}); const blade

    = document.createElement('span'); blade.classList.add('saber-blade'); blade.addEventListener('click', () => { this.setAttribute('highlight', false); }); shadow.appendChild(blade); } Adding Shadow DOM
  6. 28.

    Dispatching Events dispatchChangeEvent(status) { const options = { bubble: true,

    composed: false, details: status }; const event = new CustomEvent('sabrechange', options); this.dispatchEvent(event); }
  7. 29.

    More Callbacks class LightSaber extends HTMLElement { connectedCallback() { //

    Some initial setup. } disconnectedCallback() { // Cleanup after element destroy. } attributeChangedCallback(name, oldValue, newValue) { // Validate and handle attributes changes. } }
  8. 32.

    Stencil Stencil has dispatched Web Components, the guardians of peace

    and justice in the galaxy, to settle the conflict....
  9. 36.
  10. 37.

    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!
  11. 38.
  12. 40.

    Super Powers • Virtual DOM • JSX • TypeScript •

    Async Rendering (inspired by React Fiber) • Lazy Loading • Reactive Data-Binding
  13. 41.

    Why Stencil? • 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
  14. 42.

    import { Component, Prop, Event, Listen } from '@stencil/core'; @Component({

    tag: 'light-saber', styleUrl: 'light-saber.scss', shadow: true }) export class LightSaberComponent { @Prop() size: number; @Prop() color: string; @Prop() active: boolean; @Event() saberChange: EventEmitter; @Listen('click') onItemToggle() { const { size, color, active } = this; this.saberChange.emit({ size, color, active }); } render() { return ( <div class="saber"> <span class="saber-blade"></span> </div> ); } } Light Saber Component
  15. 43.

    Stencil API This ultimate API will spell certain doom for

    the small band of rebels struggling to restore freedom to the galaxy…
  16. 44.

    Stencil Decorators • @Component(): set tag name and associated stylesheet

    • @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
  17. 48.
  18. 49.

    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.
  19. 53.

    Articles • How I created SmileToUnlock with StencilJS • Create

    your first Web Component with Stencil JS • Getting Started With Stencil • Stencil.js: it’s finally time for vanilla web components!