👾

WebComponentsを会社で使い始めた話

2023/12/27に公開

最近では、WebComponentsを使ってデザインシステムを構築している事例を見たりしていて、WebComponentsの使い方としては「見た目など」の観点でのCustomElementsの活用が目立っているように感じます。
「見た目の観点での活用」はあまり新鮮味がないようにも感じるので、
弊社ではUIの共通化以外観点でCustomElementsを使い始めたので、良いところを含めて紹介していきたいと思います。

CustomElementsの良いところ

1. JSの処理を内部に閉じ込めることができる

DOM操作やイベントハンドラーのスコープをCustomElementsに限定できるのがメリットで、
いわゆるVanillaJSで雑にクリックイベントをつけるとなるといちいちHTMLIDをつけたりが必要で面倒だったのです。

function handleClick(e) {
  console.log(`clicked: ${e.target}`)
}
document.querySelectorAll(".clickable").forEach(el => {
   el.addEventListener("click", handleClick)
});

<button class="clickable"></button>

WebComponentsでは下記のようにイベントハンドラのスコープを用意に限定させることができるため、
これが他に依存するライブラリなしに実現できることが便利であると思いました。

class ClickerButton extends HTMLElement {
  handleClick(e) {
    console.log(`clicked: ${e.target}`)
  }
  connectedCallback() {
    this.addEventListener("click", this.handleClick)
  }
  disconnectedCallback() {
    this.removeEventListener("click", this.handleClick)
  }
}
customElements.define('clicker-button', ClickerButton);

<clicker-button></clicker-button>

2. とにかく依存が減らせるところ

当然、VueやReact、Svelteを使っても同じことは十分に実現可能です。
むしろ、親子関係をもたせたり、機能が少ないので、CustomElementsで実装するほうが面倒になることも多いと思います。

簡単な機能やUIを提供するのであればそれは、VanillaJSとサーバーサイドアプリケーションがなにかあれば十分なのかもしれません。
そもそも弊社でCustomElements導入を検討したきっかけも、Vue2のバージョンアップの対応をきっかけに、移り変わっていくフロントエンド技術(という言葉ももはや適切ではないかもしれませんが)に疲れてしまったというのをきっかけに、特にUIに依存するライブラリを導入していくことがあまり良くないことであるということに気づいたためです。

https://sizu.me/ktsn/posts/v3n2rkzcckia

特に参考になった記事

うまくCustomElementsのメリットを言語化した記事があり、大変共感を覚えたのでした。

ちょっとでも複雑なものは全部ReactやVue.js にすればよく、そうでないレベルの単純なものは Custom Elementで済むだろ派

https://scrapbox.io/fsubal/jQueryは1個の要素と複数個の要素を同じように書かせる

WebComponentsを私もこの軸で評価していて、これであれば簡単な画面はVanillaJSとCustomElementsで、複雑な画面はVueで構成することで、MPAでありながらある程度体験の良いWebアプリケーションを実装できるのかと思い、検討を進めています。

どう使っているのか?

リンクカード

弊プロダクトには通称リンクカードという、コミュニティ内部のイベントやブログのリンクを貼るとカード化するための機能があります。

この仕組みを従来はVueのコンポーネントや素朴なHTMLで実装していましたが、CustomElementsに置き換えました。

ブログの本文を表示する画面で、リンクカードを展開したい場合であっても、Vueコンポーネントの場合はVueインスタンスの管理下に置かなければなりません。
このとき、本文中にあるmustache構文が意図せず展開されてしまうケースが有るため、v-preでVueインスタンスの管轄外にしていました。
そのため、Vueのコンポーネントを記事本文で使うことができなかったのですが、CustomElementsであれば問題ありません。
WebComponentsを使えば非同期でリンクカードの内容を取得してブログのリンクカードをユーザーに表示する前に最新の情報を表示する事ができます。

dev.to流のislands Architecture

他にはdev.toにならい、RailsのMPAとVueを組み合わせたIslands Architectureの仕組みのためにWebComponentsを利用しています。
これは、特定のislandsが読み込まれたらVueのコンポーネントを読み込むための仕組みで、ほとんどのページをRails、サーバーサイドでレンダリングしたあとに、
部分的にVueを使ったりということがやりやすくするための仕組みです。本家はPreactのみで同じようなことをしていたのですが、弊社ではRailsとVueを組み合わせて実装してて、Vueだけでは実現が難しかったので、WebComponentsを使って実現していこうと考えています。

dev.to流のislands Architectureについては下記をご覧ください。
https://zenn.dev/osiro/articles/d9c886c2959b79

WebComponentsのフレームワークは使っているか?

Googleが実装したLit や GitHubが作った Catalyst
など、WebComponentsのフレームワークが出てきていますが、
弊社では今は素のWebComponentsで用途が十分なので特に利用していません。
Vueの利用を全面的にやめたりということがなければ、
複雑なことをWebComponentsでやるつもりはなく、複雑な画面はVueなどを利用するので当面、WebComponentsのフレームワークを利用することはないと思います。

まとめ

弊社でWebComponents(主にCustomElements)をデザインシステム以外の方法で活用している方法を紹介しました。
ReactやVueの技術などと組み合わせて利用する方法も今後増えていくといいかなと思っています。

OSIRO テックブログ

Discussion