lit-htmlが便利という話

9/22にFukuoka Engineers Day 2018 ~Autumn~というイベントで、2月に開催された同イベントに続いてWeb Components周辺の内容で発表してきました。

そこで取り上げたlit-htmlというライブラリが結構便利で最近気に入っているので記事にして紹介します。

lit-htmlとは?

Web Components向けにPolymerというライブラリが提供されているのですが、その開発チームが提供している『HTML in JS』を実現するためのライブラリです。位置づけ的にはJSXに近いものというイメージをしてもらえれば良いかと。

Polymerチームによって提供されていますがPolymerには依存しておらず、単体で利用できます。

npm install --save lit-html

でインストールできます。

使い方

lit-htmlはすごくシンプルなAPIを提供していて、htmlrenderという2つの関数でほとんど完結します。htmlでテンプレートを生成し、renderで実際にテンプレートをDOMにレンダリングする、という具合です。

import { html, render } from 'lit-html';

window.addEventListener('DOMContentLoaded', () => {

    const template = html`<h1>Hello, lit-html !!</h1>`;
    render(template, document.body);

});

上記コードで、bodyタグ直下にh1タグが出力されます。見てのとおり、ES2015のTemplate Literalをベースにテンプレートを構築していきます。

一見普通の文字列ベースにDOMを構築してinnerHTMLに直接突っ込むのと同じように見えますが、決定的に異なるのは、html関数を通してlit-html用のテンプレートに変換され、最終的にDOM APIによってDOM上に追加される点にあります。文字列を直接innerHTMLに設定するのに比べて遥かに安全と言えます。

変数は${}でバインドできます。

import { html, render } from 'lit-html';

window.addEventListener('DOMContentLoaded', () => {

    const name = 'lit-html';
    const template = html`<h1>Hello, ${name} !!</h1>`;
    render(template, document.body);

});

変数を直接埋め込んでいるだけだと、XSSなどを心配されるかもしれませんが、埋め込まれる文字列は適切にサニタイズされるので問題ありません。

ここまではただTemplate Literal → DOMのみの機能のようですが、いくつか拡張が加えられています。代表的なのは、イベントハンドラ用の構文です。

DOM APIでテンプレートを構築していてイベントハンドラを設定したい場合、以下のようにしなければなりません。

const button = document.createElement('button');
button.addEventListener('click', (e) => {
    console.log('clicked!!');
});

lit-htmlでは、イベント名に@を付けて関数を渡すと、自動的にイベントハンドラに登録してくれます。以下のコードは、上記をlit-htmlで記述した例です。

const template = html`<button @click="${(e) => console.log('clicked!!')}"></button>`;

lit-htmlではこの他、

  • プロパティ(input属性のvalueなど)用の.
  • プロパティを付与する/しないを制御する?

などのプレフィックスを提供していて、テンプレートを便利に記述することができます。

lit-htmlの良い点

  • シンプルなAPI
  • 変数のサニタイズがデフォルトでサポートされており文字列ベースのDOM構築に比べ安全
  • DOM APIを直接使うよりコード量が削減できる
  • 特別なビルド設定を必要としない(lit-htmlさえバンドルしてしまえば動作する)

lit-htmlの気になる点

  • テンプレートを文字列で記述するので補完などのサポートが微妙(拡張でハイライトなどは効くがEmmetなどが使えない)
  • イベントハンドラ以外に関数オブジェクトを子要素に渡す方法がない directiveでできましたね。すみません。
  • まだベータ版なので、APIが変更される可能性がある&既存のソースが古く動作しない場合が多い(一応)

lit-htmlの今後

AngularやReact、Vue.jsが普及していてそれぞれが独自にテンプレート構文を持っている現状、lit-htmlのような独自のHTML in JSライブラリなんてどこで使うのか?という話なんですが、それらのライブラリを使っている場合はそこに導入する必要はないです。(というかしない方が良い)

やはり主な使い所Polymerでの開発(というかWeb Components開発)になってくるのではないでしょうか。Polymerは次世代の基本クラスとして@polymer/lit-elementというものを開発中で、これは名前の通りlit-htmlをベースにしています。ReactがJSXならばPolymerはlit-html、といった具合になるんじゃないかと。

とはいえ特別な環境構築不要で手軽に使えるHTML in JSのライブラリで、1時間もあれば習得できるくらいシンプルなので目を通しておいて損はないんじゃないかと思います。

最後にちょっと宣伝

この記事で紹介したlit-htmlの内容も含むWeb Components本『Web Components First Book』を、池袋で開催される技術書典5というイベントで頒布予定です。Web Componentsの他、

と色々なジャンルを揃えて参加します。

フロントエンド以外にも幅広いジャンルの技術系同人誌が集うイベントで、私は今回これまでとサークル名を変更して参加しますが、福岡からは前回爆売れしたとうわさのneko-noteも引き続き参加しています。こちらは

ネタだそうです。

非常に楽しいイベントなので私の本に興味を持ってもらえた方もそうでない方も、お越しいただければ嬉しいです!

VEGA TECH サークルページ
neko-note サークルページ