Building Chat Web Components with StencilJS and Ionic 4
Tags: html, webcomponents, webdev, javascript
Published: 2019-07-29 19:29:02

---
title: Building Chat Web Components with StencilJS and Ionic 4
published: true
description: Lessons learned from writing a web component library for live chat and chatbots with StencilJS
tags: html,webcomponents,webdev,javascript
cover_image: https://i.imgur.com/H1onDMQ.png
---

Greetings to the amazing DEV community! I wanted to share with you my experience building a Web Component library using StencilJS and hear your precious feedback/comments.

Here's what I've built:

![Assister Chat](https://i.imgur.com/gt0TjLS.gif)

[Live Demo](https://assister.ai/chat/)

[GitHub](https://github.com/assister-ai/assister/blob/master/packages/chat/README.md)

# The Problem

First let's discuss why I chose Web Components, we've seen debates here on why one [would](https://dev.to/shihn/why-i-use-web-components-my-use-cases-1nip) and [wouldn't](https://dev.to/richharris/why-i-don-t-use-web-components-2cia) use web components.

You've probably seen a lot of Chatbots popping out in various webpages. These are usually proprietary add-ons that people buy from a vendor, adding them to the page with a script that pushes an `iframe` to the `body`. [Intercom](https://www.intercom.com/) and [Drift](https://www.drift.com/) seem to be popular. I was thinking about an Open Source alternative and Web Components seemed a natural fit, main reason being that` ShaddowDOM` prevents CSS conflicts with the host app.

# Technology Choice

I [struggled](https://github.com/assister-ai/assister/issues/7) **a lot** on the choice for the right tool.

## You should think long and hard about **React**

People either love or hate React, but the truth of the matter is that its influence is **HUGE**. Earlier this year, there was a long and heated discussion on [MDN Docs spring planning repo](https://github.com/mdn/sprints/issues/967#issuecomment-464257121) about why a web standards body is using a non-standard library. David Flanagan makes a sound argument IMO that attracting contributors without using React is hard. So that's one side, contributors.

The other side is people using your components. React developers most likely **will ignore your library** if they can't use it within JSX in ways they're accustomed to (`ref={}` for example).

## View vs. Logic

A simple fact about standard HTML is often times ignored, I'm guilty of this myself.

__you don't *see* anything that's not *described*__

```html
<p> I've been described, therefore I am! </p>
```

`chat-pane` is an example of breaking that rule. It contains logic and shows elements (`chat-input`) that are not described.

I was about to do the exact same with `chat-message`, I thought it'd be cool for `chat-message` to have an attribute named `meta` that contains information about its author, date sent, date read, etc. so it can render the footer based on these `meta` data. **Not cool!** That's not the HTML way of of doing things.

HTML was the *"View"* of the web way before all these front-end frameworks. If we're creating Web Components, we should strive for expanding the HTML vocabulary with the same semantics. People mock that attributes are just strings in web components. Mock all you want! This has been an elegant design of HTML that has withstood the test of time, and decouples HTML from JS/JSON.

That said, I'm not at all against having higher level components that embed application logic. However, the place for those are inside the specific application, not the general web component that we're designing for reuse.

## Ionic 4

Another choice that I made was to reuse components from `Ionic`. In retro, I'm happy with that choice. Ionic components may seem overwhelming at first, but you come to realize that they are not complex at all, things like `ion-content` and `ion-item` are essentially glorified `div`s with some useful utilities! Kudos to Ionic team's flexibility for moving to Web Components in `v4`. There're still quirks, for instance, [`ion-virtual-scroll`](https://ionicframework.com/docs/api/virtual-scroll) is currently Angular-only. My guess is Ionic Components will only get better in time. Using them in Stencil was seamless, unsurprisingly, as they are both made by the same company.

# StencilJS, does it have the answers?

Let's first talk about the **compiler** thing:

```typescript
@Component({
  tag: 'chat-message',
  styleUrl: 'message.css',
  shadow: true
})
export class Message { ... }
```

See the name of that class, `Message`? What do you think will happen if I change it to `JustinBieber`?

**Nothing!**

Nothing breaks, everything still works! You know why? Because the name of this class doesn't have any semantics at all. The class doesn't `extend` the HTMLElement class, or any other class. It's just there for that `@Component` decorator to create a host of other classes from it! Namely:

`HTMLChatMessageElement`: generated by the compiler for natively interfacing with the element. This one does extend `HTMLElement`.

`interface ChatMessage extends JSXBase.HTMLAttributes<HTMLChatMessageElement>`: this is the beauty. Remember React users? Covered by the compiler!

I was "meh" about using TypeScript at first, but you know what? Stencil automated creation of [documentation pages](https://github.com/assister-ai/assister/tree/master/packages/chat/src/components/message) from the types alone. That coupled with not having to write a `types.d.ts` and maintaining it for the project, I think it was a win.

# Conclusion

So is StencilJS the answer? IMO, hell yeah! For a specific scenario though. If you are a shorthanded dev like me, Stencil automates **a lot** for you. In doing so however, it falls in the framework of the [framework/library category](https://www.technotification.com/2019/03/frameworks-vs-libraries-computer-science.html/). On the other hand, the end results adhere perfectly to web standards. Do a `view page source` on the [demo page](https://assister.ai/chat/), fills me with joy to see this is possible again.