Custom Elementsをマークアップする - 2023秋

コンポーネント三部作の続き。

問題

Custom Elements を扱うに当たり、一般的によく紹介されるのは

いかにして Custom Elements を作るか?

という部分になる。今回自分も Lit を紹介し、実際に Lit で作られたコンポーネントに対して Controller を追加するにはどうするか、Storybook と組み合わせるには、SSR はどうする? といったアプローチで調べていったわけだけれども、Web Components を採用する主要な目的の一つは HTML, CSS マークアップ時に再利用性を高め、コーディング量を削減することである。決してコンポーネントを作ることは目的ではない。利用されるコンポーネントでないと意味がないし、

いかにして快適に Custom Elements を使ってマークアップするか?

も重要、なんなら利用の方こそ重要なのだ。今回はそういう話。

選択肢としては以下の二つがある。

  1. language server
  2. エディタ、IDE独自のカスタムデータセット

Custom Elements Language Server

0.0.5 のコードを軽く読んでみた。間違えているかもしれないけど図にしておく。

やろうとしていることは、手元のコードや npm などで配布されている Web Components のコードをスキャンして language server から支援を行うという手法になっている。はず。わざわざ各種 Web Components 作成用のライブラリに対応した plugin を内部で利用しているので、デキアイの Manifest を読み込んでいるわけではなさそう。

現状 Web Components の配布パッケージには Manifest が同梱されているとは限らないので、これは正しい選択のように見える。また恐らくだが、将来的にはこちらを本命としておくと、Emacs など古典的な開発環境でも活用できるし、いいことが多いんじゃないかと思う。

実際に

コンポーネントに期待していたことと分かったことについて考える - 2023秋(3) (2023-10-05) | あーありがち

で触れたように、

Shoelace: A forward-thinking library of web components.

については language server を利用した VS Code 拡張をインストールすることで補完が効くようになる。しかし、2023-09-26 時点で v 1.0 になったばかりの

material-components/material-web: Material Design Web Components

Material Web Components ではこの方法は利用できない。理由は後述するとして、先に二つめの選択肢について触れていこうと思う。

VS Code Custom Data

Custom Data Format: Evolving HTML and CSS language features

※ VS Code 限定の話になってしまうが、他にも似たような機能を持つものがあるかもしれない。

VS Code にはもともと Custom Data を追加できる機能がある。例えば上にも出てきた Shoelace については

.vscode/settings.json

{
  "html.customData": [
    "node_modules/@shoelace-style/shoelace/dist/vscode.html-custom-data.json"
  ]
}

と設定を追加してあげると、HTML のカスタムデータとして Shoelace の定義を追加することができ、新たに拡張をインストールしなくても Shoelace で定義された Custom Elements に対して補完が効くようになる。なんて気が利いてるんだ Shoelace.

そしてこの方法に次節の工夫を加えると Material Web Components も 1.0 時点で補完させることができるようになる。ではその方法を紹介しよう。

Custom Elements Manifest Analyzerが実は悩ましい

open-wc/custom-elements-manifest: Custom Elements Manifest is a file format that describes custom elements in your project.

Custom Elements Manifest Analyzer だが、2023-10-23 時点で以下の問題がある。

  1. Web Components の配布パッケージのコードから Manifest を作れる場合と作れない場合がある
  2. CLI では node_modules/ 以下を辿れない

1 については配布パッケージの作り方の問題のような気もするが、現状で Web Components の配布パッケージの作り方に特に何か仕様があるわけでもなさそうに見えるので、一ユーザーとしてはどっちにしろ困ることに変わりない。

2 と合わせて自分は以下のようにしてみた。

src/ でも node_modules/ でもないところに git submodule で Material Web Components を clone. 以下のような感じ。

├── depelements/
│   └── web/
├── node_modules/
├── public/
└── src/

これにより以下のように上記の問題を解決できる。

  • node_modules/ 以下ではなく depelemens/ 以下に対してなら Custom Element Manifest Analyzer は analyze を実行できる
  • 配布パッケージから取得できなかった情報が clone した src から取得でき、Manifest を生成できる

実は、node_modules/ 以下に対して、今回で言う depelements/ 以下から symlink を張るだけでパスの問題は回避できる。回避できるが、npm でインストールした Material Web Components に対して analyzer を実行しても Manifest 内の情報が十分にならなかった。これは恐らく配布パッケージにする際に Manifest に必要な情報がコードから消失してしまうか、構造的に必要な情報を取得できなくなってしまうのだろう。clone したコードからは補完に耐えうる Manifest を出力することができた。

そして以下を加える。

break-stuff/cem-tools: Tooling for generating features based on the Custom Elements Manifest

この plugin を追加して、

cem-tools/packages/vs-code-integration at main · break-stuff/cem-tools

にあるように analyzer の設定ファイルを作る。上の depelements/ 以下の分も加えると以下のような感じになる。

custom-elements-manifest.config.js

import { customElementVsCodePlugin } from 'custom-element-vs-code-integration'

export default {
  globs: [
    'src/**/*.{js,ts}',
    'depelements/**/*.{js,ts}',
  ],
  plugins: [
    customElementVsCodePlugin({
      outdir: '.vscode'
    })
  ],
  outdir: '.',
  litelement: true
}

VS Code 側の設定も忘れてはいけない。こんな感じで ok.

.vscode/settings.json

{
  "html.customData": [
    ".vscode/vscode.html-custom-data.json"
  ]
}

これで

Custom Elements Manifest生成時に同時に VS Code Custom Dataを生成し、それを利用できるようになる

これでようやく Material Web Components で追加された要素について補完を効かせながら書くことができるようになった。

図にするとこんな感じ。

VS Code と analyzer は独立して動くので、コードを watch して CustomData を生成する仕組みなどは自分で準備しないといけない。

今後Custom Elementsを作るに当たって

今回

Custom Elementsの配布パッケージにフルの情報の載った Manifest が同梱されているととてもありがたい

ことが分かった。一般配布しないまでも、Manifest の生成はワークフローに組み込んでおくことも Web Components の再利用性に大きく寄与するので、ちゃんと仕込んでいきたい。

More