How I created and published my first Stencil component

I decided that I wanted to try building a self contained Stencil component ready to use by anyone on the npm repository.

My idea was to create a web component that is heavily inspired by the Angular’s ng-container.
The plan was that st-container would have two attributes,

  • st-if, only shows the content inside the st-container if the given condition is true.
  • st-for, iterate over an array/list of items with the content like sort of a template.

Creating the project

So I started by cloning the Stencil component starter repository,

git clone stencil-container
cd my-component
git remote rm origin
npm install

then I added the boilerplate to my own repository with command,

git remote add origin

then I updated all the information in the package.json,, stencil.config.js to describe my component instead of describing Stencils starter project.

In the package.json I updated the name, description, repository, author, bugs, homepage like this:

"name": "stencil-container",
"version": "0.0.2",
"description": "Stencil Container with if-statements and for-loops",
"module": "dist/esm/index.js",
"main": "dist/index.js",
"types": "dist/types/components.d.ts",
"collection": "dist/collection/collection-manifest.json",
"files": [
"scripts": {
"build": "stencil build",
"dev": "sd concurrent \"stencil build –dev –watch\" \"stencil-dev-server\" ",
"serve": "stencil-dev-server",
"start": "npm run dev",
"test": "jest",
"": "jest –watch"
"dependencies": {},
"devDependencies": {
"@stencil/core": "^0.9.1",
"@stencil/dev-server": "latest",
"@stencil/utils": "latest",
"@types/jest": "^21.1.1",
"jest": "^21.2.1"
"repository": {
"type": "git",
"url": "git+"
"author": "Johan Axelsson",
"license": "MIT",
"bugs": {
"url": ""
"homepage": "",
"jest": {
"transform": {
"^.+\\.(ts|tsx)$": "<rootDir>/node_modules/@stencil/core/testing/jest.preprocessor.js"
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(tsx?|jsx?)$",
"moduleFileExtensions": [

In the stencil.config.js I just changed the namespace to  stencil-container.

Building the component

Now we are ready to create the stencil component in the project.

First we need to create the component folder, go ahead and create a folder named ‘st-container’ inside ‘/src/components/’ folder.

In that folder we will create two files,

st-container.spec.ts, that contains the unit tests for the component.

import { TestWindow } from '@stencil/core/testing';
import { StContainer } from './st-container';
describe('st-container', () => {
it('should build', () => {
expect(new StContainer()).toBeTruthy();
describe('rendering', () => {
let element;
beforeAll(async () => {
const window = new TestWindow();
element = await window.load({
components: [StContainer],
html: '<st-container><div>Hello, World!</div></st-container>'
it('should work without parameters', () => {
expect(element.textContent.trim()).toEqual('Hello, World!');
it('should work with st-if true', async () => {
const window = new TestWindow();
element = await window.load({
components: [StContainer],
html: '<st-container st-if="true"><div>Hello, World!</div></st-container>'
expect(element.textContent.trim()).toEqual('Hello, World!');
it('should not work with st-if false', async () => {
const window = new TestWindow();
element = await window.load({
components: [StContainer],
html: '<st-container st-if="false"><div>Hello, World!</div></st-container>'

st-container.tsx, the stencil component itself.

import { Component, Prop, Watch } from '@stencil/core';
tag: 'st-container',
shadow: true
export class StContainer {
@Prop() private stIf: string;
@Prop({ mutable: true }) private shouldRender = true;
watchHandler(newValue: string) {
console.log('The new value of stIf is: ', newValue);
this.shouldRender = false;
this.shouldRender = new Function("return " + this.stIf)();
* The component is about to load and it has not
* rendered yet.
* This is the best place to make any data updates
* before the first render.
* componentWillLoad will only be called once.
componentWillLoad() {
if (this.stIf !== undefined) {
this.shouldRender = new Function("return " + this.stIf)();
render() {
if (this.shouldRender) {
return (
<slot />
} else {
return null;

So what we have here is a very simple Stencil component. It takes a stIf as a property (@Prop()), that is given to the ‘st-container’ element. Then in ‘componentWillLoad()’ method we update the shouldRender attribute by evaluating the content of the stIf.

In the ‘render()’ method we check if the element and child elements should be rendered with the ‘if (this.shouldRender)’. If it should render we return the , the slot element is a placeholder for the content inside this component, the thing between the tags ”.

If you want to learn more about Stencil I suggest that you read the official Stencil getting started guide.

Publishing the component

So now when the component is done, the unit tests are working and the component is built. It’s time to publish it to the npm registry.

The first thing you need is an account at

Then you need to run the command ‘npm adduser‘ and follow the instructions to login with your npm account on your machine.

Then all you need to do is run ‘npm publish‘ in your projects directory and it will be uploaded if you don’t receive any errors.

You can see the final result of my st-container over here:

The nice thing with Stencil components is that they by default have zero npm dependencies, pretty sweet I would say!

No worries about this scenario with plain Stencil components!


That was all I had for you this time, you can see the full source on GitHub here:

Let me know what you thought of this article in the comments below and send me a pull request if you see any errors. 🙂


One thought on “How I created and published my first Stencil component

Add yours

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Create a website or blog at

Up ↑

%d bloggers like this: