Development of Custom Element using Vue.js #kyotojs


このスライドは社内勉強会で発表しようと思って作ったけど、年末でほとんど人がいなかったので供養として #kyotojs vol.15 で発表したものとなります。


  • potato4d
    • real name: HANATANI Takuma
  • organizations
    • ElevenBack (self-employed)
    • LINE Corp
  • Maintainer at
    • vuejs/jp.vuejs.org
    • nuxt/docs
  • Web Application Developer
    • ♥ Vue.js, Nuxt.js, Node.js(w/ TypeScript), Serverless
    • ♥ User interface, Micro interaction, Product development

今日話すこと

  • 開発したものデモ
  • Web Components - Custom Elements の開発手法について
  • Vue CLI v3 を利用した、 Vue.js ベースの Custom Elements 開発
  • 実際の開発フローについて
  • Vue.js での開発フローの罠
  • 使いどころ

注意



開発したもの


Kamishibai Viewer

  • アドカレのネタ
  • Qiita のスライドモードの埋め込みビューアー
  • SlideShare / Slides.com / SpeakerDeck はサクッと埋め込めるけど Qiita は無理だった
  • OSS で作ったらみんな嬉しそうなので開発
  • Vue.jsで作られている

Custom Elements の開発手法

そのままやるなら

  • lit-html
    • 一番薄い
    • そこまで嬉しくはない
  • lit-element
    • 人間向き
    • class & render 関数
    • 最近 rc が出てそろそろ stable に?

Custom Elements の開発手法

フレームワークでやるなら(1)

  • Angular Elements
    • Angular で作れる
    • まだばりばり開発中(らしい)
    • バンドルサイズがでかい(Angular全部入る)
    • Ivy がきたら min 12kb からになる(らしい)

Custom Elements の開発手法

フレームワークでやるなら(2)

  • Vue CLI v3
    • Vue.js で作れる
    • バンドルサイズはマシ(でもまぁフルで入る)
    • ちょっと癖がある

言いたいこと→Custom Elements はフレームワークで作れる


Vue CLI v3 での開発


ざっくりと手順


環境の構築

terminal
$ vue create my-wc-project
$ yarn add @vue/web-component-wrapper

package.json の編集

package.json
{
  "name": "my-wc-project",
  "scripts": {
    "build": "VUE_CLI_CSS_SHADOW_MODE=true vue-cli-service build --target wc --name my-component ./src/wc.ts",
    "...": "..."
  },
  "...": "..."
}

専用の Entrypoint の作成

src/wc.ts
import Vue from 'vue'

// TS の定義はない
const { default: wrap } = require('@vue/web-component-wrapper')

// ?shadow を使って Shadow DOM での Scoped CSS を有効化するのでこう読む
const { default: MyComponent } = require('./MyComponent.vue?shadow')

window.customElements.define('my-component', wrap(Vue, MyComponent))

コンポーネントのスクラッチ

src/MyComponent.vue
<template>
  <div>
    <p>
      <span>Hi, {{username}}</span>
    </p>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  props: {
    username: String
  }
})
</script>

<style scoped>
p span {
  padding-bottom: 8px;
  border-bottom: solid 2px #77CB5B;
}
</style>

ビルド

terminal
$ yarn build

完成


実際やってみる(時間があれば)


スライドだけみてるかたは⇣


……


……で、これなにが嬉しいんだっけ


Custom Element の嬉しさ(1)

  • (半)静的コンテンツへの埋め込み
    • 今回の Embed みたいに SPA とは疎結合で使いたいものは良さそう
    • Twitter Button は Web Components 製
    • Ad とかには最適なのでは
  • 内部実装の共通化
    • 最終的に出てくるのが WC という共通言語なら技術間の取り回しが良い
    • けどこれはまだまだ先だと思う

Custom Element の嬉しさ(2)

  • メモリから素直な DOM の世界に
    • 仮想 DOM とかの都合もあって今は Fw のメモリ上に DOM がある
    • 隔離された空間から public な DOM になるのは良し悪し含めある
  • Shadow DOM(Scoped CSS) 周りの統一
    • 仕様上は Shadow DOM に統合されている(2018/12現在)
    • ようやっと Fw によるオレオレ Scoped CSS じゃなくなる?

その他所感

  • 正直 SPA 作るだけなら Fw から吐き出せても「それで?」感
  • Embed / Ad などでは普通に使われそうなので良いのでは
  • Draggable みたいな Vanilla & Fw wrapper の世界にはまだ早そう
    • ああいうのはラッパーが便利な点に価値が
  • 一応多少触っておくと雑談力にはなりそう 

Thanks