Web component API construction decision tree
Tags: webcomponents, litelement, webdev, haxtheweb
Published: 2019-11-04 18:55:29

This is not intended to be the end all be all for this, but I keep getting questions that flow like this:
- How do I know when it's time to use a property?
- How did you know you needed a slot or a named slot?
- What's the SEO like on that element?

Well, I decided to start making a few flow charts to help explain the reasoning that I use when addressing these sorta of questions.
# How should I construct the API for this custom element?
![Decision tree for how to construct the API for a web component](https://thepracticaldev.s3.amazonaws.com/i/y9guy7jmk3u3yzuf0lxn.jpg)
## SEO
I put the first major inflection point at SEO. As ShadowDom allows you to hide things away to the land of JS-only, SEO is a major inflection point. If high SEO is required, you'll want to think hard about what you abstract away from users. [PatternFly Elements](https://github.com/patternfly/patternfly-elements) by Red Hat is a no-JS required, Slot first mindset. They leverage the `<slot>` tag and named slots to provide CSS selectors for their Sass driven theme and css variables engine.

This gives high SEO as the custom elements are mostly just for positioning and stylistic purposes, but you can progressively enhance things via the JS you can wire into life cycles and events.

## LightDom "Injection" / ShadowDom "eating"
I don't have a great name for this but it's an approach that I've used in the past to get fallback support for older browsers (which a search engine basically is). You can construct an element like this:
```html
<my-awesome-image src="whatever.jpg" alt="some important metadata">
  <img slot="dont-show" src="whatever.jpg" alt="some important metadata" />
</my-awesome-image>
```
Using this progressive enhancement approach, you can give the SEO overlords what they want - the "real" content, and without JavaScript. But, using this approach, I could tell the `my-awesome-image` tag that it doesn't actually implement a slot named "dont-show" so then based on how ShadowDom works, it just won't render anything for "real" users.

This gives me the chance to leverage advanced data binding of SkateJS, LitElement, VanillaJS or however I want to construct my web component in order to render our awesome looking image.

## Alternate content
I keep seeing people ask for server side rendering (SSR) and where is it with web components and they are "bass-ackwards for not having this built in". I don't believe in SSR which is probably blasphemous, but there's a good reason: Do you really, really, actually need it still? Isn't there another way to get that data out to the SEO bots? It's no longer for accessibility as all screen readers and assistive tech uses JS. HTTP2 peudo-streaming incentivizes unbundled builds, so why bother with server side rendering?

If you do need to serve up content for some reason though, I've begun opting for alternate content. This shifts the focus toward the future and modern web and off the "will it blend in IE11" vibe of SSR. I'm sure there are reasons for SSR, I just haven't run into them and it's worth exploring alternative approaches to achieving what it was giving you.

Here's a [video / write up I did about client side feature detection](https://btopro.com/the-web-components-high-performance-video-1) to deliver unbundled builds of a large app (called [HAXcms](https://haxtheweb.org/what-is-it)).

If you don't have the JS consideration and can find ways around some SEO concerns using LightDom content then you're in the clear. Web component away leveraging elements as full blown APIs. It's the [#HAXTheWeb](https://haxtheweb.org) way :)

## LitElement or VanillaJS
![LitElement vs VanillaJS decision tree](https://thepracticaldev.s3.amazonaws.com/i/bu21izkrq3yxr0znq4fx.jpg)
Do you need a lot data binding? Is this an element that's just for wrapping platform level JS functionality for convenience or to make it easier to target things with CSS? As we convert our giant portfolio (~400 web components) from PolymerElement to LitElement / VanillaJS we run through this minor decision tree.

```js
  render() {
    return html`<div>${this.aWholeBunchOfDataBinding}</div>`;
  }
```

You can replace "LitElement" here with whatever web component library you prefer but we're starting to convert everything to it unless it doesn't have a shadowRoot / render tree of it's own. In those cases, we're largely just writing vanillaJS. In our team's last 50 elements converted I'd say 80% are now LitElement and 20% are VanillaJS.

If you are trying to get off PolymerElement or just want to see what it's like to convert things and the decisions involved, our team is working on a [playlist of our journey of building elements](https://www.youtube.com/watch?v=x7o4u5tkxSc&list=PLJQupiji7J5dfgwEjRfnsjzNgnxpCRrsj&index=4&t=0s) and decisions involved.