Web Components で 社内 UI ライブラリを作っている話
WebComponents.kyoto Meetup #2 | Mar 04, 2018
じんぼ�よしひで神保 嘉秀
@jmblog
Front-end Engineer,
① 社内 UI ライブラリ「Kaizen Custom Elements」の紹介
② Web Components を採用した背景
③ 実装で工夫した点
お話すること
Web Components の仕様に関する話はしません。仕様について詳しく知りたい方はこのあたりを参考にしてください。
https://developers.google.com/web/fundamentals/web-components/
① 社内UIライブラリ「Kaizen Custom Elements」の紹介
app-elements icon-elements
<kz-app-toolbar> <kz-app-title> <kz-app-nav-menu> <kz-avatar> <kz-button> <kz-card> ""...
<kz-icon-bookmark> <kz-icon-calendar> <kz-icon-chevron-down> <kz-icon-copy> <kz-icon-download> <kz-icon-edit> ""...
Kaizen Custom Elements
• Web Components (Custom Elements + Shadow DOM) で実装
• プリミティブな要素が中心
‣ Atomic Design の Atoms(原子) から Molecules(分子) くらいの粒度
• Storybook を使ってカタログ化
• 絶賛開発中(進捗率10%くらい)
Kaizen Custom Elements の特徴
Example
src/modules/app-elements/components/kz-app-titile/index.ts
https://speakerdeck.com/mizchi/real-world-es201x-and-future?slide=39
https://kaizen-custom-elements-preview.netlify.com/
② Web Components を採用した背景
この半年間で 6 つの Single Page Application を開発
React apps
• あえて技術スタックは固定化せず多様性をもたせる
• 小さく作って捨てやすくする
• 各メンバーが最速で成果を出すことにこだわる
Angular apps
2 4
ボタンやツールバーといった要素を毎回実装するのはめんどくさい・・・ 😩
アプリケーションごとにデザインが微妙に違う・・・😩
一方で、
Angular でも React でも(何なら Vue でも Preact でも)使える
共通の UI ライブラリが欲しい 🧐
https://custom-elements-everywhere.com/
React 以外では Custom Elements の
併用は問題なさそう。
React も Basic Tests はすべて通っている。
シンプル(プリミティブ)な要素に 限定すれば、問題になることはなさそう。
Chrome / Safari はかなりサポートが進んでる。
Edge と Firefox は未対応だが、当面は Polyfill で凌げそう。
(若干の不安はあるけど)
Web Components もそろそろ「使えるレベル」になってきた印象。
まずは社内プロジェクトで試してみよう!🕺
③ 実装で苦労した点
Shadow DOM のスタイル問題
Shadow DOM のスタイル問題
Firefox と Edge は Shadow DOM にまだ対応していないので、スタイルがスコープ化されない。ShadyCSS を使えば、擬似的にスコープ化が実現できる。
lit-html v0.7
lit-html v0.7
lit-html�で軽量に作っちゃうぜー
Firefox�で�Shadow�DOM�の�スタイルが効かないぞ...�
lit-html�と�ShadyCSS�の�相性がよくない?🤔
lit-html v0.7
lit-html v0.7 Polymer v3.0
lit-html v0.7 Polymer v3.0
うまくいった
lit-html v0.7 Polymer v3.0
React + CSS in JS
React�+�CSS�in�JS�で�Shadow�DOM�のスタイル問題を�
解決できる気がする!�
であれば、Polymer�よりもすでに知⾒が溜まってる�React�を使ったほうががいいのでは?
lit-html v0.7 Polymer v3.0
React + CSS in JSチョット待てよ�🤔
React�本体を同梱するとファイルサイズが気になるし、�React�アプリで使う場合、バージョンが異なる�2つのReact�が読み込まれることになって困るか...
lit-html v0.7 Polymer v3.0
React + CSS in JSlit-html + CSS in JS
lit-html�+�CSS�in�JS�で�Shadow�DOM�のスタイル問題が�
解決できる気がする!
lit-html v0.7 Polymer v3.0
React + CSS in JSlit-html + CSS in JS
厳しかった...�😞
Shadow�Root�をもつカスタム要素に�スタイルを当てるには�:host�へのスタイル定義が必要。�⼀⽅、Firefox�では�Shadow�Root�が作成されないため�
:host�と同じスタイル定義を�CSS�in�JS�で⾏う必要がある。�⼆重管理になってしまう。
lit-html v0.7 Polymer v3.0
React + CSS in JSlit-html + CSS in JS
Polymer v3.0やっぱりお前じゃなきゃ�
ダメなのか...
lit-html v0.7 Polymer v3.0
React + CSS in JSlit-html + CSS in JS
Polymer v3.0 lit-html v0.9
lit-html v0.7 Polymer v3.0
React + CSS in JSlit-html + CSS in JS
Polymer v3.0 lit-html v0.9
lit-html�で�ShadyCSS�が�サポートされた�🎉
Shadow�DOM�のスタイル問題は�これで解決できそう(今ココ)
https://jmblog.jp/posts/2018-02-15/lit-html-with-shadycss/
create-react-app で minify できない問題
create-react-app で minify できない問題
create-react-app で生成した React アプリで Kaizen Custom Elements 使うと、
npm run build でエラーとなることが発覚。
Failed to compile.
Failed to minify the code from this file:
./node_modules/@kaizenplatform/kaizen-app-elements/kaizen-app-elements.js:1:57
Read more here: http://bit.ly/2tRViJ9
http:"//bit.ly/2tRViJ9
“いくつかのサードパーティーのパッケージは、コードを ES5 へ変換せずに(ES6のまま) npm へ公開しており、ES6 の機能をサポートしていないブラウザやツールで問題を起こす原因となっています。我々としては少なくともあと数年は ES5 で npm に公開することをおすすめします。”
(このあと、「issue を投げる」「fork する」「コピペする」などの解決策(?)が続く。)
つまり「create-react-app 使いたかったら ES6 のパッケージは使うな」
でも、Custom Elements は ES6 の Class 構文を使う必要がある。
ES5 に変換してしまうと、ブラウザでの実行時に
Failed to construct 'HTMLElement' というエラーになってしまう。
(custom-elements-es5-adapter.js を使えばいいけど、
今後のことを考えると polyfill の使用は最小限に留めたい。)
(╯°□°)╯( ┻━┻
仕方がないので、UMD 版も用意
Format File
ES Module kaizen-app-elememts.esm.js
UMD kaizen-app-elememts.umd.js
rollup.config.js
index.html で読み込んで使用
まとめ
• Web Components を本番投入しようとすると、いろいろとハマるポイントはまだ多い。
• でも、今から知見を溜めておく価値はあると思うので、まずは社内や個人の小さなプロジェクトで試してみるとよいのでは。
• lit-html や Polymer の動きも活発なので、機が熟すのを心待ちにしましょう!
まとめ
We are hiring!
Kaizen Platform ではエンジニアを募集しています。
興味のある方は https://jobs.lever.co/kaizenplatform?team=Engineer まで!