Integrating Stencil with Storybook

Published

Today I set up a new Stencil project with Storybook to build web components with. However, I had a hard time trying to get the hot module replacement (or live reloading) to work in Storybook. When using the standard dev build process, Stencil will omit the needed esm loader that Storybook’s webpack server will use to determine if a module has changed. Since I wanted to have instant feedback when developing components with Stencil, I tried to find a way to integrate both tools.

Loading Stencil components in Storybook

The most common way I found to load Stencil components in Storybook is to just setup a Stencil components project and use the Storybook HTML project setup. Then, one can load the built components by including a preview-head.html like so:

<script type="module" src="./stencil-components/stencil-components.esm.js"></script>
<script nomodule="" src="./stencil-components/stencil-components.js"></script>

Now, when running start-storybook -p 6006 -s dist, Storybook will happily include the components and load the stories. However, since this tells Storybook to load the components as static assets, the hot reloading won’t work.

Making hot reloading work

In order to include the Stencil components in webpack’s dependency graph, we need to load the components through a JS file. To do so, we’ll add a preview.js file in Storybook’s config directory .storybook in your project. The JS code in this file will be added to the preview canvas of every story and – most importantly – be recognized by the webpack build — which is exactly what we need.

When running Stencil’s build process with the --watch flag, it will produce the correct dist-output containing the esm/loader.mjs file. We’ll then use this file to call the defineCustomElements() function, which registers all of our app’s components. See the full contents of the preview.js file below:

import {defineCustomElements} from '../dist/esm/loader';

defineCustomElements();

The generated default scripts section of the project’s package.json file doesn’t contain the correct build script just yet, though. So you will need to add the following line to the scripts section:

"build.watch": "stencil build --watch"

And that’s it! You should now see all of the changes made to your components reflected in Storybook. To run both the build and Storybook, simply run these two scripts in parallel:

npm run build.watch
npm run storybook

Demo Repository

If you want to skip the hassle of implementing this in your live project and just see if it works, I’ve prepared a repository for you. 🙂

https://github.com/andreaswissel/stencil-storybook-starter