Building #webcomponents (while avoiding common pitfalls) using #stencil with end-to-end #storybook integration
Abdullah Quazi
Assistant Director @ Australian Public Service | Technical Leadership, Innovative Solutions | Web/Cross Platform Applications
My first interaction with webcomponents (WC) was interesting. Given that it was a long time ago, I didn't even fully appreciate the robustness of WC. To me it was just a piece of code (auto-completing different parts of address fields from a lookup address, hail Google) working as a blackbox and serving my purpose at a hobbyist level. Fast forward a few years and I can tell you this situation can escalate very quickly when you put a design system and CMS integration (and a couple of sleepless nights) into the mix (and that at enterprise level) and you will get a love-hate relationship with WC. To be fair, even then it had (has) its perks and nonetheless that is very interesting too, especially if you have someone to bounce ideas with or look for some guidance through brainstorming and most importantly keep it all sane at the same time (thanks again @Alex).
Now, if you are using a traditional framework few of the prominent and common pitfalls that come as a baggage (specially if you are building a big library) are:
If you are still with me, then this could be a good segway to the topic of this article, StencilJS , a completely free and open source utility, they actually call it “A Web Components Compiler”. You will see how easy it is to create WCs using StencilJS along with a documentation/guide called Storybook while avoiding the above mentioned common pitfalls (well almost). Check out the Stencil FAQ page if you are still a bit hesitant to progress.
Now let's proceed (I wish LinkedIn provided a way to add colour and syntax highlighting in the snippet area and I didn't have to use screenshots).
Prerequisite
> npm -v
8.5.5
Project Initiation
> npm init stencil
> cd bss-components
> npm install
> npm start
> code .
If you look at the code, it’s pretty straightforward. We are importing related namespaces, defining the custom tag as “my-component”, for look-and-feel we are adding a css file for it (i.e. my-componentn.css) then defining three properties (i.e. first, middle and last). Using the getText() method we are formatting the output of the text (i.e. from the @Props) and finally we are rendering the component the way we want. Like I mentioned, it's really straightforward and you can read it in detail on their website. Now that we are sort-of familiar with the basic structure let’s create a very basic but our own web-component (by the way the other two .ts files that you see in the folder structure are for testing).
Let’s create our own web-component
Now let’s actually create our very own component. How about we create a custom blockquote component with properties that can be rendered like below (let's just use BootStrap blockquote as our model for the time being):
Feature (property/attribute) wise, basically we have Title (text), Citation (source), Alignment (alignment) to customise this <blockquote> element and the equivalent html to render this (as copied from Bootstrap documentation site)
Now what we want our custom WC to look like below (if you recall the properties we mentioned above)
and render like below
Let's build the component now
> npm run generate
This will prompt you for the component tag name, in this case let’s use bss-blockquote, it will also ask you what extra files (i.e. css and those two test files) you want to generate. Simply select the default selection and press enter. You will see it generated a new component file titled as “bss-blockquote.tsx” with other related files under the /src/components/ folder.
> npm run build
Now to see it in action we can issue the command “npm start” which after completion
> npm start
So, literally in a few minutes we were able to create our first web component (well, in real life you will probably not create a blockquote component like this, but hey, you get the idea).
Let’s create something a bit more useful
Now that we’ve got some idea, let’s actually make something useful (almost like a utility but in disguise of WC) and fun
> npm run generate
Avoiding some common pitfalls
In the beginning I did mention how StencilJS can overcome some common pitfalls. I am conscious about the fact that the article is getting really long, but I will quickly show you one of the biggest issues (i.e. size and initial page load hit) that can be avoided using StencilJS.
Component size issue (initial page load hit):
It’s pretty cool, hey!
Framework defined DOM specific entry point:
SSR and SEO
“The hydrate app is a Stencil output target which generates a module that can be used on a NodeJS server to hydrate HTML and implement server side rendering (SSR)“.
You can view the documentation from StencilJS. To be honest this didn't work with my scenario, but it could work for your scenario. I will come back and revisit this section.
Accessibility
Cross Platform Compatibility
Final part: Building a documentation site for your design system (or components)
One of the key requirements while building a design system (or component libraries) is to also integrate a playground area for your end users, to build, test, and document the whole thing in isolation. Storybook has been one of the main goto options for this purpose and integrating Storybook with Stencil is simply very efficient and easy. And that is exactly what we are going to do now. We have created two components and we will see how easy it is to showcase these components in Storybook using Stencil. Ionic has published a step by step blog on this, but let's do it here together.
Add Storybook to our project
> npx sb init --type html
Once finished it will show you the following message
> npm run storybook
> npm run build
> npm run storybook
Add our first story
Once saved the Storybook should be refreshed and you should see the newly added component story on the left hand side under components.
That’s it
And that’s it. We are at the very end of the article. In this article I tried to show how easy it is to create components (or component libraries) in Stencil while avoiding common pitfalls. There is a dedicated section in Stencil documentation that outlines about how you should tackle if you are thinking of creating a design systems with Stencil. I also tried to show how easy it is to integrate Storybook with Stencil and how rich the interaction is.
Hope this helps someone who is thinking about venturing into web components.?Until next time, happy coding!.