コンテンツにスキップ

ブログを新調した

ブログを作り直そうとした経緯

以前のブログに対する不満と、素振りしてみたい技術があったので作り直しました。
以前のブログについては、以下の記事で書いています。

https://blog.sasakiy84.net/articles/my-first-blog-created/
https://blog.sasakiy84.net/articles/unified-and-vue/

以前のブログで満足できなかった箇所

以前私が実装したブログは、 Vue を使って SSG をする構成をとっていました。
SSG をしているため、SEO の観点からはなにも問題なかったのですが、実際に画面上で表示してみると記事コンテンツを取得するまでの間のロード時間で、画面が真っ白になっていました。
どうやら、Vue 単体では、nuxt 2 にあった asyncData のような機能がないらしく、SSG をしても以下のような流れになってしまうっぽいです。

  1. SSG をすることで完全な HTML が生成され、それをホスティングできるようになる
  2. ユーザーが初回アクセスで HTML をロードし、一瞬だけ完全な HTML が描画される
  3. Vue がマウントされる
  4. 記事コンテンツデータは Vue が管理しているため、コンテンツを表示している HTML の管理が Vue に渡った時点で、 Vue が持っている記事データと表示されている HTML の記事データが同期される
  5. Vue がマウントされた直後は、記事データを持っていないため、空の文字列が記事データとしてレンダリングされる(ローディング画面が表示される)
  6. 記事データが fetch され、SSG していたときと同じ記事コンテンツが表示される

具体的な実装はこの行のあたりです。

以前のブログで気に入っていた箇所

Markdown を AST にパースして、そのレンダリングを Vue に移譲することで、柔軟性のあるマークダウン描画を実装できていた点は、お気に入りでした。
たとえば、リンク先の OGP を表示させる仕様にしたい場合、そのコンポーネントを作成しておいて、リンクのノードをレンダリングするときに、そのコンポーネントを割り当てるという実装ができます。これにより、見通しがよく、保守管理がしやすいコードを書くことができていました。

使ってみたい技術

web component という仕様があります。
現在のフロントエンド開発で、コンポーネント志向は、React や Vue などのライブラリによって実現されていますが、それをブラウザの標準機能を使って実装できるようにしようというものです。
コンポーネント志向で実装する場合、React などのほうが多機能で使いやすいです。が、特定のライブラリに依存しないでコンポーネント志向ができることにも魅力を感じます。
さらに、web component は、他のライブラリからも利用することができます。

https://reactjs.org/docs/web-components.html
https://vuejs.org/guide/extras/web-components.html

また、web component をベースにした lit というライブラリも開発されているようで、完全に死に体の技術ではありません。
https://lit.dev/

実際に本番環境でも運用されている事例があるようです。たとえば、youtube のソースを見ると、web component が使われています

また、zenn などでも一部 web component を利用しているようです。
https://zenn.dev/steelydylan/articles/zenn-web-components

新しいブログの構成

使用したライブラリ・技術

マークダウンのパースと AST の操作のために、 unified のライブラリ群を利用しました。
また、コードハイライト用のライブラリや、リンク先のデータを取得するためのヘッドレスブラウザのライブラリも利用しています。

記事入稿の流れ

デプロイには GitHub Actions を使い、ホスティングには GitHub Pages を利用しています。
マークダウンによって記事を書き、main ブランチに push すると、自動でビルドが始まります。
ビルドは、以下の二段階で構成されています。

  1. リンク先の情報を取得し、json として保管する
  2. 1 で取得した情報を用いながら、マークダウンをパースし、template の HTML に格納する

ビルドが終わると、GitHub Pages 用のアーティファクトが生成され、GitHub Pages のデータが更新されます。

リンク先の情報取得について

ブログなどでは、リンクを貼り付けると自動でリンク先の情報を取得し、ユーザーに分かりやすく表示してくれる機能があると思います。
この機能を実現しようとすると、フロントエンドだけでは完結できず、バックエンドが必要になります。なぜなら、Same Origin Policy により、異なるドメインのリソース読み込みがフロントエンドにおいては制限されているためです。

そのため、普通のブログでは、リンク先の情報を取得するための API を用意しています。
たとえば、zenn のマークダウンパーサーでは、zenn が用意している API を利用できるようです。(ただし、非商用の場合)
https://www.npmjs.com/package/zenn-markdown-html

記事が納入されるタイミングが分からないようなサービスでは、上記のような API が必要です。しかし、個人ブログにおいては、記事が納入されるタイミングが分かっているので、事前に情報を取得することが可能です。
そのため、記事をデプロイするタイミングで、リンク先の情報をまとめた json を生成しておいて、それを利用することにしました。
事前に生成した情報を利用するという方式にしたことで、 OGP 画像がない場合も、スクリーンショットを撮っておいて、それを表示することができるようになりました。

web component について

現在、web component はリンクカードと Twitter のカードに利用しています。

web component は、MDN の記事でなんとなく理解し、実装しましたが、特に難しい箇所もなく実装出来ました。
https://developer.mozilla.org/en-US/docs/Web/Web_Components

ただし、Twitter のカードは zenn での実装を参考にさせていただきました。
https://zenn.dev/steelydylan/articles/zenn-web-components

宣言的っていいね

実装してみてわかったことは、生の JavaScript によって DOM 操作をすることのつらさです。私は、Vue を最初に学んだので、jQueryなどが主流だった時代を知りません。なので、宣言的な書き方が便利なんだな~と聞きつつも、どれくらい書きやすいのかについて体感していませんでした。
今回の実装では、innerHTMLなどは使わずに、手続き的に DOM を構築していったのですが、一目でマークアップの構造を把握できないため、今後デバッグをする必要が出てきたときに気が狂いそうになるだろうな、と思います。
ただ、lit などのフレームワークを使えば、ある程度緩和できそうな問題ではありますね。

今後追加していきたい機能

web component を利用して、スライドや youtube の埋め込みも可能にしたいです。
また、記事が増えてきたらタグ検索や全文検索なども実装したいです。ただ、保守性を考えて、フロントエンドで完結できるようにしたいです。