Cntlog

Web Componentを簡単に作れるStencilがとても良かった

フロントエンド

投稿日

この記事はIonic Framework / Capacitor / Stencil Advent Calendar 2020 20日目の記事です。

stencilはUIフレームのionicで利用されているWeb Componentをビルドするフレームワークです。

stencil

stencilの特徴はVue,Angular,ReactといったJavascriptフレーワークにも依存せずにScopedなComponentを開発できる点にあります。

またstencilでビルドされたJSを読み込むだけで使えるので、複数の異なったドメインにも共有することできます。
npmでの提供もできます。

stencilの始め方

npm init stencilを実行するだけで始められます。

stencil-component-starterといったスターターキットも用意されており、これを利用すると開発、テスト、ビルドがフォローされているので、すぐにstencilの気持ち良い開発環境が手にはいります。

stencilはTypeScriptに対応しており、当然このリポジトリもtypeScriptで開発できます。

コードの解説

私は当時stencilを触るのは初めてで、どう使うものなのかよくわかっていなかったので自分がコードを読んでして気がついたこと、調べたことを共有します。

npm run startをするとsyncとbuildが走り、WebComponentのファイルも生成されます。
buildされたファイルは下記のファイルから読まれており、my-componentのComponentが利用できるようになります。

index.html

  <script type="module" src="/build/stencil-starter-project-name.esm.js"></script>
  <script nomodule src="/build/stencil-starter-project-name.js"></script>

stencilはshadowDomでもLightDomでもどちらのComponentでも作成できます。
切り替え方法もとても簡単でshadowtrue,falseを切り替えるだけです。

my-component.tsx

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true,
})

Propsを受け取ることも可能です。
下記のように @Prop() name:type;を書くだけでstateを持てるのでComponent内で利用でき取り回しがしやすいです。

@Prop() first: string;

scssを使いたい場合

先程紹介したリポジトリではcssを読んでいるだけなので、scssは使えません。
scssを利用するためには、stencil-sassを利用します。

npm install @stencil/sass --save-devをしてから、stencil.config.tsに記載するだけなので簡単にscssを使用できる環境が作れます。

import { Config } from '@stencil/core';
import { sass } from '@stencil/sass';

export const config: Config = {
  plugins: [
    sass()
  ]
};

storybookを利用する

stencilでいくら簡単に利用できるようにしても、Web Componentを作っただけではなかなか開発者以外の方に使ってもらうのは難しいです。

そこで他のComponent同様にstorybookを使うとpropsや見た目がわかりやすくなり利用者が増やしやすくなります。

storybookの利用は特別なやり方があるわけではなくnpm install --save-dev @storybook/html babel-loader @babel/coreを実行して、ディレクトリやファイルを設置するだけです。

storybookで外部ファイルを読み込むpreview-head.htmlでは、下記のようなpathでstencilで作成したComponentのjsを読み込めます。

<script type="module" src="./stencil-starter-project-name/stencil-starter-project-name.esm.js"></script>
<script nomodule src="./stencil-starter-project-name/stencil-starter-project-name.js"></script>

readmeの自動生成

めちゃくちゃ感動したのですが、stencilではComponent毎のreadmenpm run buildで自動生成されます。

これをstorybookの@storybook/addon-notesと組み合わせるとプロパティもstorybookで確認できるようになりより大勢の方との開発がしやすくなります。

storybook

もう少し便利にstencilを始める

上記で紹介したstencil-component-starterをforkして、scss,storybookなどを使用できるリポジトリを作成しています。

github:contiki9/stencil-component-starter

github-pagesでstorybookも公開できるようになっています。

stencilの良さ、WebComponentの使いやすさがすぐに体感できると思います。

stencilが解決すること

実はstencilは以前から知っていたのですが、ReactでComponentとか作ったほうがいいじゃんと半ば無視をしていたのですが、phpで動いてる環境とvue.jsで作られたページが入り乱れたプロジェクトがあり、その両方にUI Componentを提供する必要がありその方法を模索してる中でstencilのことを思い出しました。

stencilに目をつけたのはShadowDomが簡単に作れるところで、Globalに存在するCSSの影響を受けずにUIを作れるので見た目が崩れないと保証された点です。

またカラーなどもプロパティで定義したものしか受け付けないのでUIにルールを適応してほか開発者に提供できるので、知らないところでUIがレイプされたといった事件を未然に防ぐことができます。

今後stencilでComponentを作るべきだなどとは思っていないのですが、長期運用やほかブランドにも展開可能なデザインシステムを作る場合は十分に選択肢に挙げられると考えています。

ルールが定義されたComponentが広域に展開されると大規模な開発や複数プロジェクトがあるとよく起こりがちなUIに関しての捉え方が変わってしまう問題が起こるのですが、利用方法を物理的に制限してしまえるshadowDomを使うことで「そんなルールでやってるなんて知らなかった」といったすれ違いコミュケーションを避けやすくなります。

毎度おなじみ、「銀の銃弾」にstencilがなるわけではないですがWeb Componentで開発することで得られる恩恵はありそうです。

最後に

どいうった粒度でUI Componentを作るのが良いかでstencilを使うメリットは変わってきます。

なんでもstencilに依存して作ってしまうとすぐに使いにくい限定的なComponentが量産されて保守もメンテもされなくなる誰も得をしない世界が起きてしまうでしょう。

Atomic Designから離れたComponent設計が必要になりますがデザインシステムを構築するにあたってstencilは「ちょうどいい」ライブラリになってくれると期待しています。

デザインシステムを構築するにあたっての考えはまた別の機会に記事にしたいと思います。