埋め込みTweetをWeb Componentsで描画するようにした
Zenn が Web Components を使って tweet を表示するようにしていたので、見習ってこのサイトにも取り入れてみた。
Web Components を利用した Zenn マークダウン部分の改善について 🔗 zenn.dev
比較
何が良いのか?
埋め込みコードの良くないところ
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ほぼだいたい完全に理解した</p>— 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 しないようにした。