miyaoka.dev

埋め込みTweetをWeb Componentsで描画するようにした

Zenn が Web Components を使って tweet を表示するようにしていたので、見習ってこのサイトにも取り入れてみた。

image

Web Components を利用した Zenn マークダウン部分の改善について 🔗 zenn.dev

ZennEditor 内のコード 🔗 github.com

比較

何が良いのか?

埋め込みコードの良くないところ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ほぼだいたい完全に理解した</p>&mdash; miyaoka / STUDIO (@miyaoka) <a href="https://twitter.com/miyaoka/status/1346720500387438593?ref_src=twsrc%5Etfw">January 6, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
  • SPA サイトではページ遷移などで再レンダリングされると 埋め込みコードの script タグが実行されないので アプリ側で twttr.widgets.load() を叩く必要がある。
  • Zenn の記事にあるように twttr.widget.load() を走らせるのはページ内の全要素が対象になるためパフォーマンスの問題が少しある。
  • この間対応した markdown 編集時の自動再読み込み を行うとロードされないのが気になっていた
  • 埋め込みコードを取得するのがだるい。(ツイートの右メニューから Embed Tweet を選んで別ページに遷移し、アニメーションが入ったあとでやっとコピーできる)

Web Components 化して良くなったところ

https://twitter.com/miyaoka/status/1346720500387438593?s=20

↓ markdown を HTML にするところで tweet の URL にマッチすれば Custom Element として出力

<embed-tweet src="https://twitter.com/miyaoka/status/1346720500387438593" />

→ Custom Element のconnectedCallback イベントで最初は URL だけ表示し、createTweet し終わったら URL は消す

  • Tweet の URL だけ貼れば表示できる
  • 各コンポーネントが自身の要素だけ load 実行する
  • 再レンダリングされても各コンポーネントのマウント時に load が行われるので、アプリ側で気にしなくていい

だめになったところ 🤮

  • 埋め込みコードは blockquote でテキスト内容が入っているのでロードされなくても情報があるが、URL だけだと情報が皆無
  • ツイ消しされるとなんのツイートだったか分からなくなって困ってしまう(VSCode 拡張作って URL 貼付け時に内容取得しに行くべきか?)
  • 埋め込みコードのオプションで Hide Conversation などが指定できない(指定できる記法を作るかも)

Custom Elements ⊂ Web Components

Web Components って書いてたけど、Custom Elements って言ったほうが正しいかもしれない。昨日初めて触ったからまだ良くわかってない。

Introduction - webcomponents.org 🔗 www.webcomponents.org

追記: lazyload 対応

パフォーマンスを計測してみたらやはりいくつもツイートを埋め込んでいると全部いっぺんにロードが走るので重い。Custom Element にして読み込み処理は少しスマートになったが、ツイート自体のアセットが重いので、そもそも必要になるまで読み込まないようにしたい。

twtter.widget.createTweet 後に iframe が挿入されるのでそこに loading="lazy" を付加すればいいかと思ってやってみたが(img と iframe は Native lazyload 可)、挿入された時点で既に読み込みは開始されている。

なので Custom Element 自体に IntersectionObserver で lazyload 処理を入れ、必要になるまで createTweet しないようにした。

mobile の before / after
mobile の before / after

PC の before / after
PC の before / after