The Ionic Framework’s team introduced a week ago, at JSConf EU, the first major iteration of the Stencil toolchain, appropriately called “Stencil One”. Stencil One compiles to optimized Web Components and progressive web apps (PWA). Developers may write a Stencil component once, and reuse it in any framework – Angular, React, Vue, Ember or with plain vanilla JavaScript, by adjusting the Stencil compiler options. Stencil One additionally provides a tool chain for enhanced user and developer experience: pre-rendering of pages, automatic generation of documentation for components, baked-in Hot Module Replacement and Style Replacement, and more.
The Stencil team describes Stencil One as “a Web Component compiler for building fast, reusable UI components and Progressive Web Apps”. Stencil components being just web components, they work in major frameworks like React or Vue; they can also be used as replacement for traditional front-end frameworks in all the browsers which support web components. Stencil One adds a number of key capabilities to the portability of Web Components, in particular “Server Side Rendering (SSR) without the need to run a headless browser, pre-rendering, and objects-as-properties”. Component documentation may also be automatically generated.
Web Components are meant to be a low-level standardized web API which aims at giving developers the possibility to extend HTML with their own custom tags. The standard, however, does not concern itself with common development issues (like efficient updates, testing or pre-rendering) – usually addressed by frameworks. Additionally, like any HTML element, web components only accept strings as properties or attributes.
Compared to using Custom Elements (a key part of the Web Components specification) directly, Stencil components feature under the hood Virtual DOM rendering, JSX syntax, asynchronous rendering pipeline (like React Fiber), and more. Developers can enjoy a development experience similar to that offered by major frameworks, while ensuring that their components will be compiled to standard-based, reusable Web Components. The Stencil team explains:
Developers often gravitate to frameworks because of their great tooling, defined structure, and ability to allow developers to build apps quickly. One of the largest goals of Stencil is to be that intersection of having great framework features and first-class tooling during development but generating future-proof web-standard code, rather than custom framework specific code.
Stencil components are written with TypeScript and JSX. A Stencil component is a class with a set of properties and methods. Class properties can be tagged with the @Prop
decorator to be attributes of the compiled target Web Component, or left as standard encapsulated class properties. Class methods similarly can be tagged with the @Method
decorator as part of the interface for the compiled target Web Component, or left as internal. Local state can also be tagged with the @State
decorator. Any changes in tagged local state will result in calling the render
property of the Stencil class. Additionally the @Watch
decorator allows developers to have a function run anytime a watched property is updated. The net result of these APIs is to define the public interface of the compiled Web Component, and the internal, reactive logic for the component.
A basic Hello World
example is as follows:
import { Component, Prop } from '@stencil/core';
@Component({
tag: 'my-component',
styleUrl: 'my-component.css'
})
export class MyComponent {
@Prop() first: string;
@Prop() last: string;
render() {
return (
<div>
Hello, my name is {this.first} {this.last}
</div>
);
}
}
Stencil will compile this class to a Web Component which can be used as any HTML element:
<my-component first="Stencil" last="JS"></my-component>
The compiled web components can be used in plain JavaScript, once they are added to the DOM with the defineCustomElements
function, exposed on the browser’s global window
object. They can also be included in the HTML rendered by any front-end framework. Full integration however with a target framework which does not fully support web components may require specific glue work. For instance, React and Polymer may require additional work as they do not fully interoperate with web components.
For the minority of browsers that do not support modern browser features and APIs, Stencil will automatically polyfill them on-demand – a feature sometimes called Differential Bundling, or Differential Loading. Browsers natively supporting a feature need not include the associated polyfill, thus reducing the size of the bundle. Browser support (with polyfills) today includes IE11 and up.
Other front-end frameworks, like Svelte, Dojo, or Lit-html, may also compile to Web Components. InfoQ recently interviewed Rich Harris, Svelte’s creator, and discussed the benefits of compiling to Web Components. Compilers can apply optimizations (like fine-grained tree-shaking, or removing unused CSS) to the target output in order to reduce bundle size and increase performance. Stencil publishes the following comparison of generated bundle size for the same application:
Stencil and Ionic are independent projects. While Ionic is the largest user and promoter of Stencil, Stencil does not prescribe any specific front-end framework.
Stencil is an open-source software available under the MIT license. Feedback is encouraged via the Stencil GitHub project and should follow Stencil’s code of conduct.