Typescriptで開発してJSファイルだけでWeb-Componentsを提供できる様な開発環境を構築する


TL;DR

Web-Components、とっても素敵なんですが、いまいちまだその真価がわからないってことが多いかと思います。
どんなユースケースが直近でweb-Componentsを使えるようになったら有用なのか?Webの開発者に喜ばれるのか?

と考えたとき、
「JSのファイルを読み込んでタグを書くといい感じのUIが提供される」
のが一番シンプルで楽なんじゃないかと思い。

<template /> を使わずWeb-ComponentsはJavascriptで完結できる開発環境を作ってみよう。
ということで、この記事です。

主要なライブラリ

※ 結論からすると まったり開発しているリポジトリがあるので いろいろぶっ飛ばしてソース読んだほうが早いって方はどうぞ。

現行で使ってるライブラリは以下です。

- Lit-html
- Typescript
- Rollup
- (Gulp)

かなりシンプルですが、これで <template /> を使用せず、最終的にバニラなJavascriptでWeb-Componentsを提供できるコードが書けます。楽!

各論

Lit-html

ES6でWeb-Componentsを実装するのであれば全然書けるのですが、どうしても <template /> でコンポーネントを定義するところが厄介です。理由としては、

  • UIだけhtml側に行ってしまうので、ファイルが分断されたりする可能性がある(underscoreやlodashの時はそのほうが良かったたのに、人間ってば自分勝手ね)
  • <template /> で定義しているhtmlの中に動的に値をアタッチしたい(この場合 <template /> を使用するとかなり面倒くさいです)

個人的にこの2点がReact, Vueとか通った身だと「面倒」と思ってしまうのです。
そこで、 Lit-html を使います。 Lit-html は特にVDOMでも何でもなく、Web-Componentsの <template /> の箇所をJSで書けるようにしてくるものなので、使い勝手も楽ちん。こういうかゆいところに手が届くライブラリはいいですね。

Typescript

上記のリポジトリの他に会社で全く同様の内容をbabel (babel v7/ES2015) を用いてやっていて個人はTypescriptでやってみようというノリです。
深い意味はありません。。。

Rollup.js

Webpackのあの割れ窓感があまり好きではなく (もちろん業務では触りますよ) 、なにかもう少しJSとかだけ上手く取扱できるやつないかなーと思って今回使ったのが Rollup.js です。

サイバーさんのこれ とかも読んでみて、なんとなくライブラリとして将来的に提供するなら Rollup.js でいいんじゃないかなーという感じで採用しています。

Gulp

Webビューの確認で使ってるだけです。
トランスパイルされたJSが更新されたらブラウザも更新して欲しい私にとってとりあえず入れてるやつです。

ただ、Rollup.jsと連携はさせないであくまでビューの確認に使っています。

環境構築やってき

Typescriptやらの基本的な設定は、いろんな方が書いている・既にやられていると思うので割愛しますが、 typescript-lit-html-plugin は必須なので、忘れずにインストールして下さい。

tsconfig.json
{
    "compilerOptions": {
        "target": "es2015",
        "moduleResolution": "node",
        "removeComments": true,
        "noImplicitAny": false,
        "noLib" : false,
        "declaration" : false,
        "preserveConstEnums": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "suppressImplicitAnyIndexErrors": true,
        "sourceMap": false,
        "allowSyntheticDefaultImports": true,
        "plugins": [
            {
                "name": "typescript-lit-html-plugin"
            }
        ]
    }
}

次にロールアップですがトランスパイル用の rollup-plugin-typescript がお亡くなりになられているので、 rollup-plugin-typescript2 を使用して下さい。これは大きなお友達とのお約束です。コンフィグは以下のようになります。

rollup.config.js
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const typescript = require('rollup-plugin-typescript2');

export default {
    input: './src/index.ts',
    output: {
        file: './dist/index.js',
        format: 'cjs'
    },
    plugins: [
        resolve({
            browser: true,
            jsnext: true,
            preferBuiltins: false,
            extensions: ['.ts', '.js', '.json']
        }),
        commonjs({
            include: 'node_modules/**'
        }),
        typescript({
            tsconfigOverride: {
                include: ['src/**/*.ts']
            }
        })
    ]
};

format などはライブラリのことを見込んで cjs (commonjs) にしています。
ココらへんは目的に応じて変更が可能です。

基本的な設定はこのくらいです。

あとは tslint なり prettier なりご自分の好きな色に染めて下さい。
Webビューに関しては、Rollupで生成したJSをhtmlで読み込んでタグを書いて実行するだけです。
とってもシンプルでしょ?

おもうこと

デザイナからこの業界に入った身としては、もし当時(4年くらい前)からWeb-Componentsが使えたら、今で言うjQueryのスライダーやそういうのがもっとシンプルに実装サイドで提供できたのではないかなー?と思っています。

今回、このゆるい開発を進めているのも先の思いがあってのことです。

リポジトリのベースのelement classは @aggre さんの FrameOO を参考にしています。ほんと勉強になります。

ということで、Web-Componetsいろいろと動きがありそうですが、
以外に簡単にJSオンリーで実装始められるので、試してみてはいかがでしょうか?ということでした!

それでは!