DEV Community

loading...
Cover image for Creating Web Components with Stencil.js

Creating Web Components with Stencil.js

Jorge Suarez
・2 min read

Raise your hand if you have ever inherited 3000, 5000, 8000+ lines of CSS in a single file, then seen some variation of the same file across many projects. That random submit button with a different hover state is pretty annoying. You want to create a component library but will have to go importing it in all the applications, with varying the stacks, and changing css selectors all over. When you move to a different framework, redo it all over again. Solution: Web Components.

"Web Components is a suite of different technologies allowing you to create reusable custom user interface components — with their functionality encapsulated away from the rest of your code — and utilize them in your web apps." - MDN

A friend recently introduced me to Stencil.js. Blessed be his soul. Stencil, created by the Ionic Framework team, is a compiler that transform your JSX, and Sass to create a Web Components bundled into an NPM package that can be imported into all your projects. We can have one source that will supply consistent branding and behavior through all your applications. Framework agnostic!

Creating a Component

With JavaScript class syntax you can name 'MyComponent'. Specify the HTML tag name and your Sass file with the @Component decorator. Pass props with the @Prop decorator and use them with JSX syntax.

/components
   /component-name
      /component-name.tsx
      /component-name.scss

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

@Component({
  tag: 'my-first-component',
  styleUrl: 'my-first-component.scss'
})
export class MyComponent {

  // Indicate that name should be a public property on the component
  @Prop() name: string;

  render() {
    return (
      <p>
        My name is {this.name}
      </p>
    );
  }
}

Distribution

Their starter template is setup for super easy publishing of your components as an NPM package. Then you can npm install or use the unpkg CDN. Add a script tag in your index.html with the src to your dist file. Voila! Your components are now registered/defined and ready to be used. distribution docs.

Usage

<my-first-component name="Max"></my-first-component>

It Gets Better

  • It lazy loads components as they become present in the DOM. If I am understanding correctly, the HTML tags are registered but the rest of the custom content loads once the browser is about to paint each component.
  • Shadow DOM. Your component is scoped. The styles will not conflict!
  • Components have a React-like life cycle. [componentWillLoad, componentDidLoad, componentWillUpdate, componentDidUpdate, componentDidUnload]
  • There is a @State decorator to handle component state.
  • And more...

I'm still learning more about this tool, and looking for other technologies to take into consideration. Let me know what you think and if you have any suggestions.

Check out the docs to try it out.

Launch Video

Discussion (5)

Collapse
atl3tico profile image
atl3

Just like polymer 3 🤗

Collapse
jorgerafaelsj profile image
Jorge Suarez Author • Edited

Cool, do you have any thoughts on advantages Polymer offers over Stencil?

Collapse
atl3tico profile image
atl3

Not really no. Just saying all this stuff you can do it with polymer 3(wich is not fully shipped yet)
I like the lazy-component by default part indeed😄

Collapse
isaacdlyman profile image
Isaac Lyman

This is awesome. How good is browser support for shadow DOM/web components these days?

Collapse
jorgerafaelsj profile image
Jorge Suarez Author • Edited

Hi Isaac! Stencil.js falls back on scoped CSS when Shadow DOM is not supported by the browser so it would still work to my understanding.

IE, Edge, and Firefox are not supported yet according to this source: caniuse.com/#feat=shadowdomv1 (Firefox can be enabled, its just not the default)